如何Mock父类方法调用?子类方法测试Mock难题求助
解决方案:Mock父类方法同时保留子类逻辑
这个问题我之前也碰到过,核心是要只Mock父类的foo()方法,同时保留子类foo()的真实逻辑,而不是直接Mock子类的整个方法。我先还原一下你的代码场景,再给出具体的测试方案:
先假设你的代码结构
父类 Parent
public class Parent { public String foo() { // 原实现总是返回"error" return "error"; } }
子类 Child
public class Child extends Parent { private boolean someVariableSetElseWhere; public void setSomeVariableSetElseWhere(boolean value) { this.someVariableSetElseWhere = value; } @Override public String foo() { String superResult = super.foo(); // 只有当super返回null且变量为true时,才调用bar() if (superResult == null && someVariableSetElseWhere) { bar(); } return superResult; } public void bar() { // 需要验证是否被调用的方法 } }
正确的测试方案(使用Mockito Spy)
你之前的问题大概率是直接Mock了子类的foo()方法,导致整个方法被替换,直接返回null,跳过了子类的逻辑。我们需要用**Spy(部分Mock)**来保留子类foo()的真实实现,只Mock父类的foo()返回值:
import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import static org.mockito.Mockito.*; @RunWith(MockitoJUnitRunner.class) public class ChildTest { // Spy会创建真实的Child实例,同时允许我们Mock部分方法 @Spy private Child childSpy; @Test public void testFoo_whenSuperReturnsNullAndVariableIsTrue_thenBarIsCalled() throws Exception { // 关键:将Spy转换为父类类型,Mock父类的foo()方法返回null doReturn(null).when((Parent) childSpy).foo(); // 设置变量为true,满足if条件的第二个判断 childSpy.setSomeVariableSetElseWhere(true); // 调用子类的foo()方法 childSpy.foo(); // 验证bar()方法被调用了一次 verify(childSpy, times(1)).bar(); } @Test public void testFoo_whenSuperReturnsError_thenBarIsNotCalled() { // 这里不Mock父类,用真实的父类实现返回"error" childSpy.setSomeVariableSetElseWhere(true); childSpy.foo(); // 验证bar()从未被调用 verify(childSpy, never()).bar(); } }
为什么这个方案有效?
@Spy创建的是真实的子类实例,所以子类foo()的逻辑会完整执行;doReturn(null).when((Parent) childSpy).foo()这一步,是针对父类的foo()方法进行Mock,当子类调用super.foo()时,会返回我们预设的null;- 这样就能完美覆盖你需要的测试场景:既控制父方法的返回值,又保留子类的判断逻辑,从而验证
bar()是否被正确调用。
常见错误点提醒
如果你之前尝试直接Mock子类的foo()(比如when(child.foo()).thenReturn(null)),那么整个foo()方法都会被Mockito替换,不会执行你写的子类逻辑,自然也不会触发bar()的调用判断,这就是为什么你会看到Child.foo()始终返回null的原因。
内容的提问来源于stack exchange,提问作者scolem
相关产品推荐
相关产品推荐

