使用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.
相关产品推荐
相关产品推荐

