java - 如何注入(inject)同一接口(interface)的多个模拟

标签 java spring dependency-injection mocking mockito

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

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

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

(有一个 doWork() 方法将检查条件并调用 A 或 B)。

如何将每个服务的模拟注入(inject)到适当的变量中?

我的Junit有这个:

@InjectMocks ServiceCaller classUnderTest = new ServiceCaller();

@Mock SomeService mockServiceA;
@Mock SomeService mockServiceB;

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

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

最佳答案

将模拟命名为 serviceA 和 serviceB 就足够了。来自 Mockito documentation :

Property setter injection; mocks will first be resolved by type, then, if there is several property of the same type, by the match of the property name and the mock name.

在你的例子中:

@InjectMocks ServiceCaller classUnderTest;

@Mock SomeService serviceA;
@Mock SomeService serviceB;

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

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

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

@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); 

关于java - 如何注入(inject)同一接口(interface)的多个模拟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21054057/

相关文章:

java - 如何针对各种屏幕调整应用程序(JFrame)?

java - Spring & Java Generics - 在抽象 Controller 中获取一项服务的实例

php - 依赖注入(inject)容器处理 PHP 网站的哪些部分?

spring - Transactional TestNG 测试导致 Large Objects 可能无法在自动提交模式下使用

java - 找不到为 JSP 文件生成的 Java 源代码

c# - SignalR 中的简单注入(inject)器注册问题

mvvm - ViewModel 到 ViewModel 的通信

java - 使用 Android Studio 重命名和应用程序 ID

java - 如何识别来自PDA/桌面/服务器的Web请求?

java - 如何使用 Tracer 在 Camel 中记录流的主体?