You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用PowerMock时,如何Mock抽象类父类的calculate方法进行JUnit测试?

解决方案:无需PowerMock Mock父类方法

场景说明

现有父类Parent,代码如下:

class Parent{
    public String calculate(String input){
       // 包含大量外部系统调用和复杂计算逻辑
    }
}

另有抽象类AbsChild继承自Parent,代码如下:

public abstract class AbsChild extends Parent{
    
    public String calculatePayments(String abc, String xyz){
       
        String ZXC = doSomething(abc);
        // 其他代码逻辑
    }
    
    private String doSomething(String abc){
       
        String STR = super.calculate(abc);
        // 其他代码逻辑
    }
}

需求与问题

需要为AbsChild的calculatePayments方法编写JUnit测试用例,Mock父类Parent的calculate方法(该方法包含大量外部调用与复杂计算)。尝试的测试代码如下:

public class AbsChildTest extends AbsChild{

     @Test
     public void testCalculatePayments(){
   
         Parent parent = mock(Parent.class);
         when(parent.calculate(anyString())).thenReturn("str");
         this.calculatePayments("abc", "xyz");

     }

}

当前测试仍会调用父类calculate的真实方法并抛出异常,询问能否在不使用PowerMock的情况下实现正确Mock。


可以用Mockito的spy机制实现,不需要依赖PowerMock。你之前的测试无效,是因为你mock了一个独立的Parent对象,但测试类继承AbsChild后,this指向的是真实的AbsChild实例,它的父类方法还是会调用真实逻辑,和你mock的那个Parent对象没关系。

方法1:使用Mockito Spy Mock父类方法

修改后的测试代码如下:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AbsChildTest {

    @Test
    public void testCalculatePayments(){
        // 创建AbsChild的Spy实例,指定调用真实方法(除了被Mock的部分)
        AbsChild childSpy = Mockito.mock(AbsChild.class, Mockito.CALLS_REAL_METHODS);
        
        // Mock从父类继承的calculate方法,指定返回值
        Mockito.when(childSpy.calculate(Mockito.anyString())).thenReturn("str");
        
        // 调用真实的calculatePayments方法
        childSpy.calculatePayments("abc", "xyz");
        
        // 这里可以添加断言,验证方法执行结果或逻辑分支
    }
}

原理:

  • Mockito.mock(AbsChild.class, Mockito.CALLS_REAL_METHODS)会生成抽象类的实例,默认执行真实方法,但被Mock的方法会返回预设值。
  • 当doSomething里调用super.calculate时,实际会触发我们Mock的calculate方法(因为Spy实例覆盖了父类方法的行为),不会执行真实的外部调用逻辑。

方法2:微调原代码提升测试性(可选)

如果允许对AbsChild做微小修改,可以重写calculate方法并改为调用this.calculate而非super.calculate,让测试更直观:

public abstract class AbsChild extends Parent{
    
    public String calculatePayments(String abc, String xyz){
        String ZXC = doSomething(abc);
        // 其他代码逻辑
    }
    
    private String doSomething(String abc){
        // 改为调用this.calculate
        String STR = this.calculate(abc);
        // 其他代码逻辑
    }
    
    // 重写父类方法,默认调用父类实现
    @Override
    public String calculate(String input){
        return super.calculate(input);
    }
}

调整后,测试逻辑和方法1一致,但语义更清晰,后续维护测试也更方便。


内容的提问来源于stack exchange,提问作者Rajib Sharma

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 23:44:51