Mockito @Mock对象无视新when..return定义返回同一对象问题排查
问题原因分析
你遇到的问题核心是测试实例生命周期导致的Mock对象共享冲突:
- 你使用了
@TestInstance(TestInstance.Lifecycle.PER_CLASS),这会让整个测试类只生成一个实例,所有测试方法共用同一个@Mock标记的DateMgr对象。 - 即使你尝试重置Mock,若时机或方式不对,之前测试方法设置的存根依然会残留,导致后续测试的Mock行为不符合预期。
解决方案
方案1:改用默认测试实例生命周期(推荐)
直接删除@TestInstance(TestInstance.Lifecycle.PER_CLASS)注解,JUnit5默认采用PER_METHOD模式——每个测试方法都会创建全新的测试类实例,@Mock和@InjectMocks也会重新初始化,彻底隔离不同测试的Mock对象,避免互相干扰。
修正后的测试代码:
@ExtendWith(MockitoExtension.class) public class TestSeries{ // 补充漏写的class关键字 @Mock DateMgr dt; @InjectMocks Series s; @BeforeEach // 将@BeforeAll改为@BeforeEach,适配PER_METHOD的实例生命周期 public void setup(){ // 一些初始化操作 } // 生成指定数量日期的方法 public List<LocalDate> getMockDates(int c){/* 实现代码 */} // 模拟dt.getDates(f,always)方法调用 public void mockDates(List<LocalDate> dates){ when(dt.getDates(any(), anyBoolean())).thenReturn(dates); } @Test public void test1(){ List<LocalDate> dates1 = getMockDates(2); mockDates(dates1); List<LocalDate> processedDates = s.calculate(param1, param2); // 补充调用对象s. // 一些断言操作 } @Test public void test2(){ List<LocalDate> dates2 = getMockDates(3); mockDates(dates2); List<LocalDate> processedDates = s.calculate(param1, param2); // 一些断言操作 } }
方案2:保留PER_CLASS但强制重置Mock(适合必须共享实例的场景)
如果业务场景要求必须使用PER_CLASS生命周期,需在每个测试方法执行前重置Mock,确保存根状态干净:
@ExtendWith(MockitoExtension.class) @TestInstance(TestInstance.Lifecycle.PER_CLASS) public class TestSeries{ @Mock DateMgr dt; @InjectMocks Series s; @BeforeAll public void setup(){ // 一些初始化操作 } @BeforeEach // 新增:每个测试前重置Mock public void resetMock(){ Mockito.reset(dt); } // 其余方法同原代码,注意修正s.calculate()的调用和class关键字 }
额外修正点
原测试代码存在两处笔误,需同步修正:
- 测试类定义漏写
class关键字:public TestSeries{→public class TestSeries{ - 测试方法中调用
calculate时漏写对象前缀:calculate(param1,param2)→s.calculate(param1,param2)
内容的提问来源于stack exchange,提问作者Ink Oveflow
相关产品推荐
相关产品推荐

