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

如何用Mockito模拟方法中带参构造创建的对象?

使用Mockito 3.5+ Stub带参构造函数创建的对象

问题场景

现有带参构造的POJO类:

public class Pojo{
    private String field1;
    private String field2;

    public Pojo(String field1, String field2){
        this.field1 = field1;
        this.field2 = field2;
    }
}

待测试类AnInjectMock的runTransaction方法中直接通过构造函数创建Pojo对象,需要仅用Mockito(3.5及以上版本)Stub该构造生成的对象,且支持用any()匹配构造参数:

public class AnInjectMock{

    private ServiceClass serviceClass;
    
    public void runTransaction(Param1 param1, Param2 param2){
        Pojo pojo = new Pojo(param1.getFiel1(), param2.getField2());
        serviceClass.createTransaction(pojo, /*其他参数*/);
    }
}

解决方案

利用Mockito 3.5+提供的mockConstructionAPI,可拦截指定类的构造函数调用,匹配任意参数并返回自定义的mock对象,步骤如下:

1. 补充POJO的getter(可选,用于测试验证/Stub行为)

如果需要在测试中验证Pojo的属性或Stub方法返回值,需为Pojo添加getter方法:

public class Pojo{
    private String field1;
    private String field2;

    public Pojo(String field1, String field2){
        this.field1 = field1;
        this.field2 = field2;
    }

    public String getField1() {
        return field1;
    }

    public String getField2() {
        return field2;
    }
}

2. 编写测试代码

使用mockConstruction拦截Pojo的构造,结合参数匹配器匹配任意String类型的构造参数,并设置mock对象的行为:

import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;
import static org.mockito.Mockito.*;

public class AnInjectMockTest {

    @Test
    void testRunTransaction() {
        // 创建ServiceClass的mock并注入测试实例
        ServiceClass mockService = mock(ServiceClass.class);
        AnInjectMock testInstance = new AnInjectMock();
        testInstance.serviceClass = mockService;

        // 拦截Pojo的构造,匹配任意两个String参数
        try (MockedConstruction<Pojo> mockedPojo = mockConstruction(Pojo.class,
                (mock, context) -> {
                    // 设置mock对象的方法返回值
                    when(mock.getField1()).thenReturn("stubbed_field1");
                    when(mock.getField2()).thenReturn("stubbed_field2");
                },
                // 指定构造参数匹配规则:任意两个String类型参数
                withSettings().constructorArgs(anyString(), anyString()))) {

            // 构造测试用的Param1/Param2 mock
            Param1 param1 = mock(Param1.class);
            Param2 param2 = mock(Param2.class);
            when(param1.getFiel1()).thenReturn("任意值");
            when(param2.getField2()).thenReturn("任意值");

            // 执行测试方法
            testInstance.runTransaction(param1, param2);

            // 验证serviceClass的方法是否被调用了mock的Pojo
            verify(mockService).createTransaction(any(Pojo.class), any());
            
            // 可选:获取构造出的mock对象,验证其行为
            Pojo constructedMock = mockedPojo.constructed().get(0);
            verify(constructedMock, times(1)).getField1();
        }
    }
}

关键说明

  • mockConstruction通过constructorArgs(anyString(), anyString())匹配任意两个String类型的构造参数,只要new Pojo()传入的是String参数,就会被拦截并返回mock对象。
  • 使用try-with-resources包裹MockedConstruction,测试结束后会自动清理mock上下文,避免影响其他测试用例。
  • 如果需要保留Pojo构造函数的真实逻辑(比如初始化字段),可添加defaultAnswer(CALLS_REAL_METHODS)配置,否则默认返回mock的空实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 01:40:00