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

如何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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 04:00:29