如何@InjectMocks的Mockito工作?(How does Mockito @Inject

2019-07-21 00:56发布

我的问题是:

我有几个Web服务类测试,所有继承的通用服务的方法。 而不是写为每个单元测试,我想我可以通过功能区打破测试套件向下(即,三个组的测试方法,每个依赖于不同的底层DAO方法调用)。

我的建议做的是:

@Mock StateDAO mockedStateDao;
@Mock CountyDAO mockedCountyDao;
@Mock VisitorDAO mockedVisitorDao;

然后调用:

@InjectMocks CountyServiceImpl<County> countyService = new CountyServiceImpl<County>();
@InjectMocks StateServiceImpl<State> stateService = new StateServiceImpl<State>();
@InjectMocks VisitorServiceImpl<Visitor> visitorService = new VisitorServiceImpl<Visitor>();

我如何才能确保每个mockedDAO将被注入到正确的服务? 难道是比较容易自动装配所有三个(而不是使用@InjectMocks)?

我使用Spring,Hibernate和...的Mockito

Answer 1:

那么尼古拉斯回答几乎是正确的,但不是猜测只是看的javadoc的InjectMocks ,它包含了更多的细节;)

对我来说,它的怪异有在一个单一的测试这么多的服务,这感觉不对,作为一个单元测试或集成测试。 在单元测试是错误的,因为还有你有太多的合作者,它看起来并不像定向(或固体)对象。 在集成测试,因为你的代码测试与数据库的整合不是嘲笑它,它的怪异。

对于1.9.5快速引用您有:

标记应在其上进行注射的字段。

允许速记模拟和间谍注射。 最大限度地减少重复模拟和间谍注射。 的Mockito将尝试通过构造器注入,setter注入,或财产注射以便并且如下所述仅任一注入嘲笑。 如果有以下策略失败,那么会的Mockito不报告故障; 也就是说,你必须自己提供的依赖。

  1. 构造函数注入; 最大的构造选择,那么参数与仅在测试中声明嘲笑解决。

    注:如果无法找到参数,则传递null。 如果非mockable类型想要的东西,然后构造器注入将不会发生。 在这种情况下,你将不得不满足依赖自己。

  2. 物业setter注入; 模拟考试将首先按类型解决,那么,如果存在多个相同类型的属性,属性名的匹配和模拟名称。

    注1:如果你有相同类型(或同一消失)的特性,这是更好的名字了匹配属性的所有@Mock注释字段,否则可能的Mockito感到困惑和注射不会发生。

    注2:如果@InjectMocks实例之前未初始化,并有一个无参数的构造函数,那么它将与此构造初始化。

  3. 场注入; 模拟考试将首先按类型解决,那么,如果存在多个相同类型的财产,由字段名的匹配和模拟名称。

    注1:如果你有相同类型(或同一消失)领域,它更好地命名与匹配字段中的所有批注@Mock领域,否则可能的Mockito感到困惑和注射不会发生。

    注2:如果@InjectMocks实例之前未初始化,并有一个无参数的构造函数,那么它将与此构造初始化。



Answer 2:

如果您有多个服务和想更换与基于Spring的环境模拟对象的DAO的,我会建议使用Springockito: https://bitbucket.org/kubek2k/springockito/wiki/Home

其中这里也提到: 与注射嘲笑的Mockito成一个Spring bean

然后,您的TestClass可能是这样的:

@RunWith (SpringJUnit4ClassRunner.class)
@ContextConfiguration (loader = SpringockitoContextLoader.class, locations =    {"classpath:/org/example/package/applicationContext.xml"})
public class NameOfClassTest {

    @Autowired
    @ReplaceWithMock 
    StateDAO mockedStateDao;

    @Autowired
    @ReplaceWithMock 
    CountyDAO mockedCountyDao;

    @Autowired
    @ReplaceWithMock 
    VisitorDAO mockedVisitorDao;

在您的@测试或@Before了Methode你可以设置你的嘲弄标准方式的Mockito:

Mockito.doReturn(null).when(mockedCountyDao).selectFromDB();


Answer 3:

那么,静态方法MockitoAnnotations.initMocks(Object)被用来引导的全过程。

我不肯定知道它是如何工作的,因为我还没有浏览源代码,但我会实现它是这样的:

  1. 扫描过Object与成员变量的类@Mock注解。
  2. 对于每一个,创建该类的一个模拟,并将其设置到该构件。
  3. 扫描过Object与成员变量的类@InjectMocks注解。
  4. 扫描类每个找到的构件的会员它可与在(2)中创建的模拟对象(即,这里的字段是一个父类/接口,或同一类中的一个被注入,作为模拟对象声明类),并将其设置到该构件。


Answer 4:

没关系,看着online-的InjectMocks注释与@Mock注释对待任何一个领域,是静态的作用域(类宽),所以我真的不能机制保障的嘲笑会去到正确的服务。 这是有些思想实验在功能层面,而不是一流水平试图单元测试。 想我就自动装配这个东西与Spring ...



文章来源: How does Mockito @InjectMocks work?