如何模拟在其他方法中赋值的本地对象属性以完成JUnit测试正向流程覆盖
解决方案
方案1:利用Mockito Answer 操作传入validatorService.validate的参数(推荐,无需修改业务代码)
你不需要捕获方法内新建的ValidationResponse对象,这个对象会作为入参传递给validatorService.validate方法,直接在mock该方法时修改入参状态即可:
@Test public void testPositiveFlow() { // 准备测试入参和预期值 Object testObj = new Object(); String expectedMsg = "校验通过"; // mock validate方法逻辑 when(validatorService.validate(eq(testObj), any(ValidationResponse.class))) .thenAnswer(invocation -> { // 拿到方法传入的ValidationResponse实例 ValidationResponse response = invocation.getArgument(1); // 设置校验状态为通过,控制后续分支走向 response.setValid(true); return expectedMsg; }); // 调用被测方法 String result = testBean.someMethod(testObj); // 断言返回值,同时补充Positive flow对应逻辑的断言即可 assertEquals(expectedMsg, result); }
如果ValidationResponse没有提供setValid的公开方法,可以用Mockito自带的反射工具修改对应私有字段,或者参考下方方案。
方案2:抽取对象创建逻辑到可重写方法(轻微修改业务代码,兼容性好)
对原有业务代码做最小改动,把ValidationResponse的创建抽成单独的protected方法:
// 业务类新增工厂方法 protected ValidationResponse createValidationResponse() { return new ValidationResponse(); } // 修改someMethod的对象创建逻辑 public String someMethod(final Object obj) { final ValidationResponse validationResponse = createValidationResponse(); // 其余原有逻辑保持不变 }
测试时用Mockito Spy被测类,替换工厂方法的返回值为你提前mock好的ValidationResponse对象:
@Test public void testPositiveFlow() { // 构建被测类的Spy对象 TestBean testSpy = Mockito.spy(new TestBean()); // mock ValidationResponse并指定isValid返回值 ValidationResponse mockResponse = Mockito.mock(ValidationResponse.class); when(mockResponse.isValid()).thenReturn(true); // 替换工厂方法返回值 doReturn(mockResponse).when(testSpy).createValidationResponse(); // 其余mock和测试逻辑正常编写即可 }
方案3:使用PowerMock拦截构造方法(不推荐,仅用于无法修改业务代码的场景)
如果完全不能修改业务代码,可以引入PowerMock拦截ValidationResponse的构造调用,直接返回mock对象:
// 测试类添加PowerMock注解 @RunWith(PowerMockRunner.class) @PrepareForTest(TestBean.class) // 填写被测类的类名 public class TestBeanTest { @Test public void testPositiveFlow() throws Exception { ValidationResponse mockResponse = Mockito.mock(ValidationResponse.class); when(mockResponse.isValid()).thenReturn(true); // 拦截ValidationResponse的无参构造调用 PowerMockito.whenNew(ValidationResponse.class).withNoArguments().thenReturn(mockResponse); // 其余测试逻辑正常编写即可 } }
内容的提问来源于stack exchange,提问作者mevada.yogesh
相关产品推荐
相关产品推荐

