使用@InjectMocks时sharedServA依赖为空,无参构造为何出现该问题?
问题分析与解决方案
这绝对不是Mockito的异常行为,而是你对@InjectMocks的工作逻辑理解有偏差——咱们一步步拆解问题:
首先明确@InjectMocks的核心规则:它只能注入你已经在测试类中声明了Mock/Spy/真实实例的依赖,对于没有提供对应实例的依赖,Mockito没办法凭空生成对象注入,只能让它保持null,这和被测类有没有显式声明构造方法无关。
为什么你会有这个误解?
你看到的“仅在被测类有带参构造时出现null”的说法,其实是指Mockito的注入优先级逻辑:
- 优先级1:构造方法注入:如果被测类有带参构造,Mockito会优先尝试用测试类中匹配的Mock实例来构造对象。如果构造方法的某个参数没有对应的Mock,Mockito会传入
null(如果构造方法允许的话),这时候会出现null。 - 优先级2:Setter方法注入:如果没有合适的构造方法,Mockito会寻找对应属性的
setXxx()方法,用匹配的Mock注入。 - 优先级3:字段注入:如果前两种都不行,Mockito会直接给被测类的字段赋值——不管字段上有没有
@Inject注解,但前提是你已经为这个字段提供了Mock/Spy/真实实例。
你的场景是被测类用默认无参构造,Mockito走的是字段注入,但你只给RepositoryA声明了@Mock,ShareServiceA没有任何对应的实例,所以Mockito找不到可以注入的对象,自然就留空了,这完全符合规则。
解决办法
根据你的测试需求,有几种方案可选:
Mock ShareServiceA(最常用)
如果你不需要测试ShareServiceA的真实逻辑,直接给它也加@Mock注解,Mockito会自动创建Mock实例注入:public class ServiceAImplTest { @Mock private RepositoryA repA; @Mock // 新增这个注解 private ShareServiceA sharedServA; @InjectMocks private ServiceAImpl serviceAImpl; @Before public void setUp() { MockitoAnnotations.openMocks(this); } // 测试方法... }使用真实的ShareServiceA实例
如果你需要验证ShareServiceA的真实行为,可以直接创建真实实例,然后手动注入:public class ServiceAImplTest { @Mock private RepositoryA repA; private ShareServiceA sharedServA = new ShareServiceA(); // 真实实例 @InjectMocks private ServiceAImpl serviceAImpl; @Before public void setUp() { MockitoAnnotations.openMocks(this); // 手动注入真实实例 ReflectionTestUtils.setField(serviceAImpl, "sharedServA", sharedServA); } }用@Spy创建部分Mock的真实实例
如果需要ShareServiceA的大部分真实逻辑,但要Mock其中个别方法:@Spy private ShareServiceA sharedServA = new ShareServiceA(); @InjectMocks private ServiceAImpl serviceAImpl;
这样处理后,sharedServA就不会再是null,测试时也不会触发空指针异常了。
内容的提问来源于stack exchange,提问作者artsylar
相关产品推荐
相关产品推荐

