如何使用JUnit5、Mockito的mockConstruction mock构造器编写测试用例
基于Mockito mockConstruction 实现无PowerMock的JUnit5测试
前置依赖要求
请确保项目引入的Mockito版本 >= 3.4.0,该版本开始原生支持构造函数mock能力,完全兼容JUnit5,无需PowerMock依赖。
实现思路
被测类的构造函数内连续实例化了两个对象:
- 先通过传入的
soapUrlnew 出ExternalApiServiceWsProxy实例 - 再将这个代理实例作为参数 new 出
ExternalApiServiceHelper实例赋值给成员变量
我们可以通过两个独立的MockedConstruction监听器分别拦截两个类的构造过程,在拦截回调中:
- 校验构造参数是否符合预期
- 拿到构造生成的mock实例,验证两个实例的传递关系
- 最后断言getter方法返回的就是我们mock出的Helper实例
MockedConstruction基于try-with-resources实现作用域管控,仅在try块内生效,退出块后自动恢复原有构造逻辑,不会污染其他测试用例。
完整测试代码
import org.junit.jupiter.api.Test; import org.mockito.MockedConstruction; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; class ExternalApiClientHandlerTest { private static final String TEST_SOAP_ENDPOINT = "https://test-soap.service.com/api"; @Test void shouldInitDependenciesCorrectlyWhenConstruct() { // 同时开启两个类的构造拦截,统一在try-with-resources中管理生命周期 try (MockedConstruction<ExternalApiServiceWsProxy> wsProxyMockControl = Mockito.mockConstruction( ExternalApiServiceWsProxy.class, (wsProxyMock, constructContext) -> { // 校验WsProxy构造时传入的URL参数正确 assertEquals(TEST_SOAP_ENDPOINT, constructContext.arguments().get(0)); // 此处可按需给WsProxy的方法加桩,例:when(wsProxyMock.call(any())).thenReturn(testResp); } ); MockedConstruction<ExternalApiServiceHelper> helperMockControl = Mockito.mockConstruction( ExternalApiServiceHelper.class, (helperMock, constructContext) -> { // 校验Helper构造时传入的就是前面生成的WsProxy mock实例 Object passedProxyArg = constructContext.arguments().get(0); assertSame(wsProxyMockControl.constructed().get(0), passedProxyArg); // 此处可按需给Helper的方法加桩 } )) { // 执行被测逻辑:实例化handler ExternalApiClientHandler handler = new ExternalApiClientHandler(TEST_SOAP_ENDPOINT); // 断言校验 // 1. 两个依赖类都只被实例化了1次 assertEquals(1, wsProxyMockControl.constructed().size()); assertEquals(1, helperMockControl.constructed().size()); // 2. getter返回的Helper实例就是mock生成的实例 assertSame(helperMockControl.constructed().get(0), handler.getExternalApiServiceHelper()); } } }
扩展说明
- 不需要嵌套写try块,多个
MockedConstruction可以平铺在同一个try-with-resources中管理,代码可读性更好 - 如果后续要测试
ExternalApiClientHandler中其他调用Helper的方法,直接在mockConstruction的回调中给对应mock加桩即可,和普通Mockito mock的用法完全一致
内容的提问来源于stack exchange,提问作者Sammy Pawar
相关产品推荐
相关产品推荐

