如何用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
相关产品推荐
相关产品推荐

