我有课:
@AllArgsConstructor
public class QuestionInfoService {
QuestionInfoRepository repository;
}
我想创建一个测试,为此类创建一个间谍:
@Spy QuestionInfoService questionInfoService
同时我希望用模拟的
questionInfoService
来初始化 QuestionInfoRepository
:
@RunWith(MockitoJUnitRunner.class)
public class QuestionInfoServiceTest {
@Mock
QuestionInfoRepository repository;
@Spy
QuestionInfoService questionInfoService = new QuestionInfoService(repository);
@Test
public void shouldFetchQuestions() {
System.out.println(questionInfoService.getRepository());
}
}
根据文档我应该能够做到这一点:
@Spy Foo spyOnFoo = new Foo("argument");
https://javadoc.io/doc/org.mockito/mockito-core/2.8.47/org/mockito/Spy.html
虽然当我运行测试时结果是:
null
如何使用@Mock注释的字段初始化@Spy?
您的测试与 Mockito 文档中的示例之间存在微小但至关重要的差异:
@Spy Foo spyOnFoo = new Foo("argument");
将常量文字值传递给 Foo 的构造函数,而
@Mock QuestionInfoRepository repository;
@Spy QuestionInfoService questionInfoService = new QuestionInfoService(repository);
将未初始化的字段传递给 QuestionInfoService 的构造函数。
Mockito/JUnit 需要创建测试类的一个实例(每个测试方法一个实例)。字段初始值设定项在初始化时执行,只有在初始化之后,Mockito 才能为带注释的字段赋值。由于
repository
在初始化时为 null,因此 QuestionInfoService
实例已使用 null
存储库创建,然后分配给该字段。稍后对 repository
的分配对现有 QuestionInfoService 实例的影响为零。
解决方案?手动指示 Mockito 在您的设置方法中创建间谍:
@Mock QuestionInfoRepository repository;
QuestionInfoService questionInfoService;
@Before
void setup() {
// here, `repository` has already been assigned a value by Mockito via the annotation:
questionInfoService = spy(new QuestionInfoService(repository));
}
类似的问题(尽管没有
@Spy
注释),其原因和解决方案在 推论:对象生命周期和魔法框架注释中概述。
参考资料: