如何在@InjectMocks注入前Stub @Mock对象方法适配构造函数初始化?
问题
类A的构造函数会从注入的对象B中获取属性,存入变量时还用了requireNonNull做非空校验。测试时需要在构造函数注入前Stub Mock对象B的方法,但发现@InjectMocks会在@BeforeEach之前完成注入,导致Mock方法返回null触发非空校验,测试根本跑不起来。这种场景下还能使用@Mock和@InjectMocks吗?
对应的代码示例:
class A { String c; A(B b) { c = requireNonNull(b.getC()); } } @ExtendWith(MockitoExtension.class) class ATest { @Mock B b; @InjectMocks A a; @BeforeEach void setUp() { when(b.getC()).thenReturn(""); } @Test void test() {} }
解决方案
可以用@Mock,但不适合直接用@InjectMocks——因为@InjectMocks的初始化时机确实早于@BeforeEach,没法提前Stub依赖的方法。给你两种靠谱的调整方式:
方式一:手动创建A实例
直接放弃@InjectMocks,在@BeforeEach里先把Mock对象的方法Stub好,再手动new出A的实例。这样就能保证构造函数执行时,Mock的方法已经能返回预期值:
@ExtendWith(MockitoExtension.class) class ATest { @Mock B b; A a; // 去掉@InjectMocks注解 @BeforeEach void setUp() { when(b.getC()).thenReturn(""); a = new A(b); // 手动初始化A } @Test void test() {} }
方式二:用@BeforeAll提前Stub(仅限无状态Mock)
如果Mock对象B是无状态的,不会在测试用例之间被修改,可以把Stub逻辑放到@BeforeAll里——注意这个注解修饰的方法必须是static的,对应的Mock对象也要加static:
@ExtendWith(MockitoExtension.class) class ATest { @Mock static B b; // 必须加static @InjectMocks A a; @BeforeAll static void setUp() { // 方法必须是static when(b.getC()).thenReturn(""); } @Test void test() {} }
不过更推荐方式一,因为@BeforeAll的static Mock容易在测试用例之间造成状态污染,手动初始化的方式不仅灵活可控,逻辑也更清晰。
内容的提问来源于stack exchange,提问作者Konstantin Pelepelin
相关产品推荐
相关产品推荐

