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

使用Mockito测试类时无法Mock第三方类属性应如何处理?

问题根因
  • 你当前测试中创建的MyServiceImpl是Mockito生成的Mock对象,该对象的所有成员属性默认值为null,你单独声明的@Mock GatewayProxyInvoker不会自动注入到这个Mock的MyServiceImpl实例中,所以调用真实方法时会触发空指针。
  • 单元测试的核心原则是隔离被测对象的外部依赖,你当前的被测类是MyTransformer,它仅依赖MyService接口,不需要关联MyServiceImpl的内部实现逻辑,你的测试写法本身不符合单元测试的隔离要求。
解决方案

方案一(推荐:符合单元测试隔离原则)

直接MockMyService接口的行为,不需要调用MyServiceImpl的真实实现,仅验证MyTransformer.myMethod正确调用了依赖的MyService.doSomething方法即可,MyServiceImpl的内部逻辑应该放到单独的MyServiceImplTest测试类中覆盖。
修改后的测试代码:

@RunWith(MockitoJUnitRunner.class)
public class MyTransformerTest {
    @InjectMocks
    private MyTransformer transformer;

    // 直接Mock接口,不需要用实现类
    @Mock
    private MyService myService;
    
    @Test
    public void myMethodTest() throws Exception {
        // 构造入参
        Context context = new Context();
        Input input = new Input();
        Something something = new Something();
        
        // 执行测试方法
        Output output = transformer.myMethod(context, input, something);
        
        // 验证依赖方法被正确调用,结果符合预期
        assertNotNull(output);
        verify(myService, times(1)).doSomething(any(Context.class), any(Input.class), any(ServiceInput.class));
    }
}

方案二(适用集成测试场景:需要调用MyServiceImpl真实逻辑)

如果你确实需要在当前测试中走MyServiceImpl的真实执行流程,可以用反射工具将Mock的gatewayProxyInvoker手动注入到MyServiceImpl实例中,这里可以用Spring Test自带的ReflectionTestUtils工具类,也可以用原生JDK反射实现。
修改后的测试代码:

@RunWith(MockitoJUnitRunner.class)
public class MyTransformerTest {
    @InjectMocks
    private MyTransformer transformer;

    // 这里用Spy而不是Mock,Spy默认会调用真实方法,不需要额外加doCallRealMethod
    @Spy
    private MyServiceImpl myService;
    
    @Mock
    private GatewayProxyInvoker gatewayProxyInvoker;
    
    @Before
    public void init() {
        // 手动将mock的gatewayProxyInvoker注入到myService的属性中
        ReflectionTestUtils.setField(myService, "gatewayProxyInvoker", gatewayProxyInvoker);
    }
    
    @Test
    public void myMethodTest() throws Exception {
        Response myResponse = new Response();
        when(gatewayProxyInvoker.invoke(any(Class.class), any(Context.class), any(Request.class))).thenReturn(myResponse);
        
        // 执行测试
        transformer.myMethod(/*valid input params*/);
        
        // 可添加对应验证逻辑
    }
}

注意:方案二中使用@Spy而不是@Mock修饰MyServiceImpl,@Spy会基于真实的类实例生成代理对象,默认调用真实方法,比@Mock加doCallRealMethod的写法更符合该场景的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:36:04