使用Mockito @Spy注解时无法初始化@Mock字段的问题
问题原因
问题出在字段初始化顺序:Java会先执行类中字段的赋值语句(也就是new QuestionInfoService(repository)),之后Mockito才会处理@Mock注解创建真正的Mock实例。因此当你创建Spy对象时,repository还只是null,导致Spy内部的成员变量也变成了null。
正确解决方案
方案1:使用@InjectMocks自动注入
用@InjectMocks让Mockito自动将已初始化的Mock实例注入到Spy对象中,无需手动new:
@RunWith(MockitoJUnitRunner.class) public class QuestionInfoServiceTest { @Mock QuestionInfoRepository repository; @Spy @InjectMocks QuestionInfoService questionInfoService; @Test public void shouldFetchQuestions() { System.out.println(questionInfoService.getRepository()); // 输出Mock实例 } }
Mockito会通过构造函数注入(因QuestionInfoService使用了@AllArgsConstructor),自动把repository Mock注入到Spy里。
方案2:在@Before方法中手动创建Spy
利用@Before方法的执行时机(所有测试方法前执行,此时@Mock已完成初始化),手动创建Spy:
@RunWith(MockitoJUnitRunner.class) public class QuestionInfoServiceTest { @Mock QuestionInfoRepository repository; QuestionInfoService questionInfoService; @Before public void setup() { questionInfoService = Mockito.spy(new QuestionInfoService(repository)); } @Test public void shouldFetchQuestions() { System.out.println(questionInfoService.getRepository()); // 输出Mock实例 } }
这种方式更灵活,适合需要自定义Spy创建逻辑的场景。
方案3:JUnit 5兼容写法(MockitoExtension)
如果使用JUnit 5,可通过MockitoExtension配合@BeforeEach确保Mock先初始化再创建Spy:
@ExtendWith(MockitoExtension.class) public class QuestionInfoServiceTest { @Mock QuestionInfoRepository repository; QuestionInfoService questionInfoService; @BeforeEach public void setup() { questionInfoService = Mockito.spy(new QuestionInfoService(repository)); } @Test public void shouldFetchQuestions() { System.out.println(questionInfoService.getRepository()); } }
内容的提问来源于stack exchange,提问作者fascynacja
相关产品推荐
相关产品推荐

