用mockito @Spy注释的spy不会初始化@Mock字段

问题描述 投票:0回答:1

我有课:

@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?

java unit-testing mockito stub partial-mocks
1个回答
0
投票

您的测试与 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
注释),其原因和解决方案在 推论:对象生命周期和魔法框架注释中概述。

参考资料:

© www.soinside.com 2019 - 2024. All rights reserved.