Mockito @InjectMocks如何工作? [英] How does Mockito @InjectMocks work?

查看:1152
本文介绍了Mockito @InjectMocks如何工作?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的问题:



我有几个Web服务类来测试所有这些类从一个通用服务继承他们的方法。而不是为每个测试写一个单元测试,我想我可以通过功能区域(即三组测试方法,每个依赖于不同的底层DAO方法调用)来将测试套件断开。



我建议做的是:

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

然后调用:

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

如何确定每个mockedDAO将被注入正确的服务?
自动连接所有三个(而不是使用@InjectMocks)更容易?



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


解决方案

好的尼古拉斯答案几乎是正确的,而不是猜测只看 InjectMocks ,它包含更多的细节;)



<对我来说,在单次测试中拥有这么多服务是奇怪的,它不觉得正确,单元测试或集成测试。在单元测试中,这是错误的,因为你有太多的协作者,它看起来不像面向对象(或SOLID)。在集成测试中,这很奇怪,因为您测试与DB集成的代码不会模拟它。



对于1.9.5中的快速参考,您有:


标记应该执行注射的字段。



允许速记模拟和间谍注射。
最小化重复模拟和间谍注射。
Mockito将尝试仅通过构造函数注入,设置注入或属性注入来注入模拟,如下所述。如果以下任何策略失败,则Mockito将不会报告失败;即,您将必须自己提供依赖项。


  1. 构造函数注入选择最大的构造函数,那么参数只能在测试中声明的模拟解决。



    注意:如果无法找到参数,则会传递null。如果需要不可嘲笑的类型,则不会发生构造函数注入。在这种情况下,您必须自己满足依赖关系。


  2. 属性设置器注入将首先通过类型解析mocks,然后如果有多个属性相同的类型,通过属性名称和模拟名称的匹配。



    注1:如果你具有相同类型的属性(或相同的擦除),最好使用匹配的属性来命名所有@Mock注释的字段,否则Mockito可能会感到困惑,注入不会发生。



    注意2:如果@InjectMocks实例未被初始化并且具有无参数构造函数,那么将使用此构造方法初始化。


  3. 字段注入; 首先通过类型解析mocks,然后,如果有多个属性是相同类型,通过字段名称和模拟名称的匹配。 / p>

    注1:如果您有相同类型(或相同的擦除)的字段,则为呃将所有@Mock注释的字段命名为匹配的字段,否则Mockito可能会感到困惑,注入不会发生。



    注2:如果@InjectMocks实例未被初始化并且具有无参数构造函数,则将使用此构造函数进行初始化。




Here's my question:

I have several web services classes to test that all inherit their methods from a generic service. Rather than write a unit test for each, I figure I can break the test suite down by functional areas (i.e. three groups of test methods, each relying on a different underlying DAO method call).

What I propose to do is:

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

then call:

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

How can I be sure that each mockedDAO will be injected into the correct service? Would it be easier to autowire all three (rather than use @InjectMocks)?

I'm using Spring, Hibernate, and Mockito...

解决方案

Well nicholas answer is almost correct, but instead of guessing just look at the javadoc of InjectMocks, it contains more details ;)

To me it's weird to have so many Service in a single test, it doesn't feel right, as a unit test or as an integration test. In unit test it's wrong because well you have way too much collaborators, it doesn't look like object oriented (or SOLID). In integration tests, it's weird because the code you test the integration with the DB not mock it.

For a rapid reference in 1.9.5 you have :

Mark a field on which injection should be performed.

Allows shorthand mock and spy injection. Minimizes repetitive mock and spy injection. Mockito will try to inject mocks only either by constructor injection, setter injection, or property injection in order and as described below. If any of the following strategy fail, then Mockito won't report failure; i.e. you will have to provide dependencies yourself.

  1. Constructor injection; the biggest constructor is chosen, then arguments are resolved with mocks declared in the test only.

    Note: If arguments can not be found, then null is passed. If non-mockable types are wanted, then constructor injection won't happen. In these cases, you will have to satisfy dependencies yourself.

  2. 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.

    Note 1: If you have properties with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching properties, otherwise Mockito might get confused and injection won't happen.

    Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.

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

    Note 1: If you have fields with the same type (or same erasure), it's better to name all @Mock annotated fields with the matching fields, otherwise Mockito might get confused and injection won't happen.

    Note 2: If @InjectMocks instance wasn't initialized before and have a no-arg constructor, then it will be initialized with this constructor.

这篇关于Mockito @InjectMocks如何工作?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆