Mockito测试遗留代码时,如何验证Context状态值的修改?
解决Mockito测试中无法验证Context状态更新的问题
你的测试失败的核心原因是:Mockito的RETURNS_DEEP_STUBS创建的深层mock不会自动维护对象状态。你预设了context.getState().getValue()返回4.12345,这个mock的getValue()方法只会一直返回这个固定值,哪怕你调用了setValue()——因为mock不是真实的对象,它没有实现“调用setValue就更新内部值”的逻辑。
要验证process()方法是否正确调用了setValue并传入了正确的参数,你需要拆分mock层级,手动mock每个依赖对象,然后捕获交互行为或者验证参数。
修改后的测试代码
@RunWith(MockitoJUnitRunner.class) public class TestSampleClass { SampleClass sample = new SampleClass(); @Mock private Context context; @Mock private State state; // 假设State是context.getState()返回的类型 @Test public void testProcess() { // 1. 预设context.getState()返回我们mock的State对象 Mockito.when(context.getState()).thenReturn(state); // 2. 预设state.getValue()返回初始值4.12345 Mockito.when(state.getValue()).thenReturn(4.12345); // 执行被测方法 sample.process(context); // 方式一:直接验证setValue是否被调用了正确的参数 Mockito.verify(state).setValue(4.123); // 方式二:如果MathUtil.roundToThree的结果可能有精度问题,用ArgumentCaptor捕获参数再断言 ArgumentCaptor<Double> captor = ArgumentCaptor.forClass(Double.class); Mockito.verify(state).setValue(captor.capture()); assertEquals(4.123, captor.getValue(), 0.0001); // 用更小的精度阈值更稳妥 } }
关键说明
- 避免使用
RETURNS_DEEP_STUBS:深层mock虽然写起来简洁,但在需要验证交互时会变得不直观,而且不利于排查问题。拆分mock层级(分别mock Context和State)是更清晰的做法。 - 验证交互而非状态:因为mock没有真实状态,所以不能通过调用
getValue()来判断是否更新,而是要验证setValue()是否被调用了预期的参数——这是Mockito测试无状态mock的标准方式。 - 精度问题:断言浮点数时,建议使用一个极小的阈值(比如0.0001),而不是0.0,避免因为浮点数计算的精度误差导致测试失败。
内容的提问来源于stack exchange,提问作者Ashish
相关产品推荐
相关产品推荐

