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

如何使用JUnit5、Mockito的mockConstruction mock构造器编写测试用例

基于Mockito mockConstruction 实现无PowerMock的JUnit5测试

前置依赖要求

请确保项目引入的Mockito版本 >= 3.4.0,该版本开始原生支持构造函数mock能力,完全兼容JUnit5,无需PowerMock依赖。

实现思路

被测类的构造函数内连续实例化了两个对象:

  1. 先通过传入的soapUrl new 出ExternalApiServiceWsProxy实例
  2. 再将这个代理实例作为参数 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 03:45:36