如何在@InjectMocks注入前完成@Mock对象的方法预配置?
解决方案
核心问题是Mockito的初始化逻辑中,@InjectMocks标注类的实例化会在@BeforeEach回调之前执行,因此在@BeforeEach中对@Mock对象打桩时,ClassB的构造方法已经执行完成,final字段stuff已经被赋值为null。
方案1:纯Mockito环境,最小化手动代码
放弃@InjectMocks注解,手动在实例初始化块中完成打桩和类实例化,仅需1行手动创建代码,符合尽量减少手动逻辑的要求:
@ExtendWith(MockitoExtension.class) class MyTest{ @Mock private ClassA classA; private ClassB classB; // 实例初始化块,在测试类实例化后、生命周期回调前执行 { // 先打桩再实例化ClassB Mockito.lenient().when(classA.getStuff()).thenReturn("预期返回值"); classB = new ClassB(classA); } //Tests omitted }
这里添加lenient()是为了避免Mockito报未使用的打桩警告,如果你所有测试用例都会触发getStuff调用可以去掉
方案2:Spring Boot测试环境,完全注解实现
如果使用Spring Boot测试框架,可以用@MockBean+@BeforeEach实现完全注解化配置,不需要手动创建ClassB实例:
@SpringBootTest class MyTest{ @MockBean private ClassA classA; @Autowired private ClassB classB; @BeforeEach void stub(){ // Spring上下文初始化时会先处理@MockBean的打桩,再初始化ClassB,因此打桩会生效 Mockito.when(classA.getStuff()).thenReturn("预期返回值"); } //Tests omitted }
方案3:纯注解无手动代码实现(需要自定义Answer类)
如果完全不想写手动创建逻辑,可以自定义Answer类,通过@Mock注解的answer参数指定默认返回逻辑:
// 自定义Answer类,处理getStuff方法的返回 public class ClassAStubAnswer implements Answer<Object> { @Override public Object answer(InvocationOnMock invocation) throws Throwable { if (invocation.getMethod().getName().equals("getStuff")) { return "预期返回值"; } // 其他方法返回默认值 return Mockito.RETURNS_DEFAULTS.answer(invocation); } }
测试类代码:
@ExtendWith(MockitoExtension.class) class MyTest{ // 通过注解指定Answer,mock初始化时就自带打桩逻辑 @Mock(answer = ClassAStubAnswer.class) private ClassA classA; @InjectMocks private ClassB classB; //Tests omitted }
该方案完全不需要手动编写对象创建逻辑,所有配置均通过注解实现
内容的提问来源于stack exchange,提问作者why_vincent
相关产品推荐
相关产品推荐

