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

Mockito:如何Mock另一个方法内部调用的方法?

如何正确Mock内部调用的b.getBName(id)方法

首先得明确核心:要让a.getAName()调用时跳过真实的b.getBName(id)执行,关键是确保A类里依赖的B对象是Mock实例,而非真实对象,同时给这个Mock实例设置好预期返回行为。

下面结合最常用的Mockito框架,分场景给出具体解决方案:

场景1:A类通过构造器注入B对象

如果你的A类是构造器注入B的结构:

public class A {
    private final B b;

    public A(B b) {
        this.b = b;
    }

    public String getAName(String id) {
        return "A_" + b.getBName(id);
    }
}

对应的测试代码应该这么写:

import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.junit.jupiter.api.extension.ExtendWith;

import static org.mockito.Mockito.when;
import static org.junit.jupiter.api.Assertions.assertEquals;

@ExtendWith(MockitoExtension.class)
public class ATest {
    // 先Mock出B对象
    @Mock
    private B mockB;

    @Test
    void testGetAName() {
        // 1. 创建A实例时,传入Mock的B对象
        A a = new A(mockB);
        
        // 2. 设置Mock行为:当调用mockB.getBName("testId")时,返回指定值
        when(mockB.getBName("testId")).thenReturn("MockedB");
        
        // 3. 调用A的目标方法
        String result = a.getAName("testId");
        
        // 4. 验证结果
        assertEquals("A_MockedB", result);
        // 此时不会执行真实的b.getBName,因为用的是Mock的B实例
    }
}

场景2:A类通过Setter/字段注入B对象

如果A类是用Setter或者Spring的@Autowired字段注入B:

public class A {
    @Autowired
    private B b;

    public String getAName(String id) {
        return "A_" + b.getBName(id);
    }
}

测试时可以用@InjectMocks自动注入Mock的B对象:

@ExtendWith(MockitoExtension.class)
public class ATest {
    @Mock
    private B mockB;

    @InjectMocks // 自动把Mock的B注入到A实例中
    private A a;

    @Test
    void testGetAName() {
        when(mockB.getBName("testId")).thenReturn("MockedB");
        
        String result = a.getAName("testId");
        
        assertEquals("A_MockedB", result);
    }
}

你之前代码可能出问题的原因

  • 没有使用Mock的B对象:如果A实例依赖的是真实的B对象,那必然会执行真实的getBName方法,一定要确保A关联的是你Mock出来的B实例。
  • Mock行为参数不匹配:比如你设置的是when(mockB.getBName("wrongId")),但调用时传的是"testId",这时候Mock不会生效,若B是真实对象就会走真实逻辑。
  • 误用@Spy注解:如果给B用了@Spy而非@Mock,默认会执行真实方法,需要用doReturn(...).when(spyB).getBName(...)来强制覆盖。

特殊情况:B的方法是静态方法

如果b.getBName是静态方法,需要用MockedStatic来Mock:

@Test
void testGetANameWithStaticB() {
    try (MockedStatic<B> mockedStaticB = Mockito.mockStatic(B.class)) {
        mockedStaticB.when(() -> B.getBName("testId")).thenReturn("MockedStaticB");
        
        A a = new A();
        String result = a.getAName("testId");
        
        assertEquals("A_MockedStaticB", result);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 08:35:23