如何注入同一接口的多个模拟

我希望测试的Java类(称为)有这个:ServiceCaller

@Autowired @Qualifier(value="serviceA")
SomeService serviceA;

@Autowired @Qualifier(value="serviceB")
SomeService serviceB;

(有一种方法可以检查条件并调用A或B)。doWork()

如何将每个服务的模拟注入到相应的变量中?

我的朱尼特有这个:

@InjectMocks ServiceCaller classUnderTest = new ServiceCaller();

@Mock SomeService mockServiceA;
@Mock SomeService mockServiceB;

然而,当我运行测试以检查在正确条件下调用的服务A / B时,我得到空指针,因为模拟尚未注入。

显然,这是因为对同一接口的多个依赖关系()。有没有办法在声明模拟服务时指定限定符?或者我需要为依赖关系设置器并设置老式的方式?SomeService


答案 1

将模拟服务命名为 A 和 serviceB 就足够了。来自 Mockito 文档

属性设置器注入;模拟将首先按类型解析,然后,如果存在多个相同类型的属性,则通过属性名称和模拟名称的匹配进行解析。

在您的示例中:

@InjectMocks ServiceCaller classUnderTest;

@Mock SomeService serviceA;
@Mock SomeService serviceB;

请注意,使用@InjectMocks时,不必手动创建类实例。

尽管如此,我个人更喜欢使用构造函数注入依赖项。它使在测试中注入模拟更容易(只需使用模拟调用构造函数 - 没有反射工具或(这很有用,但隐藏了某些方面))。此外,使用 TDD 还可以清楚地看到测试类所需的依赖项,并且 IDE 还可以生成构造函数存根。@InjectMocks

Spring Framework完全支持构造函数注入:

@Bean
public class ServiceCaller {
    private final SomeService serviceA;
    private final SomeService serviceB;

    @Autowired
    public ServiceCaller(@Qualifier("serviceA") SomeService serviceA,
                         @Qualifier("serviceB") SomeService serviceB) { ... }

    ...
}

可以使用以下命令测试此代码:

@Mock SomeService serviceA;
@Mock SomeService serviceB;

//in a setup or test method
ServiceCaller classUnderTest = new ServiceCaller(serviceA, serviceB); 

答案 2

您可以使用“name”属性来定义您的实例,如下所示:

@Mock(name="serviceA") SomeService serviceA;
@Mock(name="serviceB") SomeService serviceB;

推荐