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


我想

测试的Java类(称为ServiceCaller)具有:

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

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

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

我的朱尼特有这个:

@InjectMocks ServiceCaller classUnderTest = new ServiceCaller();
@Mock SomeService mockServiceA;
@Mock SomeService mockServiceB;

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

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

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

属性 setter 注入;模拟将首先按类型解析,然后, 如果有多个相同类型的属性,则通过匹配 属性名称和模拟名称。

在您的示例中:

@InjectMocks ServiceCaller classUnderTest;
@Mock SomeService serviceA;
@Mock SomeService serviceB;

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

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

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

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

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

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

当你有相同类型的依赖关系时,由于相同类型的属性,mockito停止注入depedencies。要参照@osiris256通过以下方式解决此问题:

class ServiceLayer{
   @Autowired
   @Qualifier("bean1")
   private InterfaceA typeA;  
   @Autowired
   @Qualifier("bean2")
   private InterfaceA typeB;  
}

您的测试类应该是:

@RunWith(SpringRunner.class)    
class ServiceLayerTest{
  @Mock(name = "typeA")
  private InterfaceA typeA;  
  @Mock(name = "typeB")
  private InterfaceA typeB;  
  @InjectMocks
  ServiceLayer serviceLayer;
  @Before
  public void initialiseBeforeTest(){
     MockitoAnnotations.initMocks(this);
  }
  // here goes your test 
  @Test
   public void test(){
     // use your when then .....
  }
}

注意:如果您使用的是SpringRunner并使用@MockBean这将不起作用,您必须替换为 @Mock(name=") 以引用@osiris256。

相关内容

  • 没有找到相关文章

最新更新