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

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

问题描述

这是我的问题:

我有几个 Web 服务类来测试它们是否都从通用服务继承了它们的方法.我认为我可以按功能区域(即三组测试方法,每组依赖于不同的底层 DAO 方法调用)分解测试套件,而不是为每个测试套件编写单元测试.

我建议做的是:

@Mock StateDAO mockedStateDao;@Mock CountyDAO 嘲笑CountyDao;@Mock VisitorDAO 嘲笑VisitorDao;

然后调用:

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

如何确保每个 mockedDAO 都被注入到正确的服务中?自动装配所有三个(而不是使用@InjectMocks)会更容易吗?

我正在使用 Spring、Hibernate 和 Mockito...

解决方案

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

对我来说,在一个测试中包含这么多服务很奇怪,作为一个单元测试或作为一个集成测试感觉都不对.在单元测试中这是错误的,因为你有太多的合作者,它看起来不像面向对象(或 SOLID).在集成测试中,这很奇怪,因为您测试与数据库集成的代码没有模拟它.

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

<块引用>

标记应执行注入的字段.

允许速记模拟和间谍注入.最大限度地减少重复的模拟和间谍注入.Mockito 将尝试仅通过构造函数注入、setter 注入或属性注入按顺序注入模拟,如下所述.如果以下任一策略失败,则 Mockito 不会报告失败;即您必须自己提供依赖项.

  1. 构造函数注入;选择最大的构造函数,然后使用仅在测试中声明的模拟来解析参数.

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

  2. Property setter injection; mocks会先通过type解析,如果有多个property同类型,则通过property name和mock name的匹配.

    注意 1: 如果你有相同类型(或相同擦除)的属性,最好用匹配的属性命名所有 @Mock 注释字段,否则 Mockito 可能会混淆并且注入失败'不会发生.

    注2:如果@InjectMocks 实例之前没有初始化并且有一个无参数的构造函数,那么它将使用这个构造函数进行初始化.

  3. 字段注入; mocks会先通过类型解析,如果有多个属性相同类型,则通过字段名和mock名的匹配.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天全站免登陆