这是我的问题:
我有几个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 ......
答案 0 :(得分:21)
尼古拉斯的回答几乎是正确的,但不是猜测只看InjectMocks的javadoc,而是包含更多细节;)
对我而言,在一次测试中拥有如此多的服务是奇怪的,它感觉不对,作为单元测试或集成测试。在单元测试中它是错误的,因为你有太多的协作者,它看起来不像面向对象(或SOLID)。在集成测试中,它很奇怪,因为您测试与数据库集成的代码没有模拟它。
要获得1.9.5中的快速参考,您需要:
标记应在其上进行注射的区域。
允许速记模拟和间谍注射。 最大限度地减少重复模拟和间谍注射。 Mockito将尝试仅通过构造函数注入,setter注入或属性注入按顺序注入模拟,如下所述。如果以下任何一种策略失败,那么Mockito将不会报告失败;即你必须自己提供依赖。
构造函数注入; 选择最大的构造函数,然后使用仅在测试中声明的模拟解析参数。
注意:如果找不到参数,则传递null。如果需要非可模拟类型,则不会发生构造函数注入。在这些情况下,您必须自己满足依赖性。
属性设置器注入; 模拟将首先按类型解析,然后,如果存在多个相同类型的属性,则通过属性名称和模拟名称的匹配来解析。< / p>
注1:如果你有相同类型(或相同的擦除)的属性,最好用匹配的属性命名所有@Mock带注释的字段,否则Mockito可能会感到困惑并且注入赢了'发生了。
注2:如果之前没有初始化@InjectMocks实例并且有一个no-arg构造函数,那么它将使用这个构造函数进行初始化。
- 醇>
字段注入; 模拟首先按类型解析,然后,如果有多个相同类型的属性,则匹配字段名称和模拟名称。
注1:如果你有相同类型(或相同的擦除)的字段,最好用匹配的字段命名所有@Mock带注释的字段,否则Mockito可能会感到困惑并且注入赢了'发生了。
注2:如果之前没有初始化@InjectMocks实例并且有一个no-arg构造函数,那么它将使用这个构造函数进行初始化。
答案 1 :(得分:3)
如果您有多个服务并想在基于Spring的环境中用模拟对象替换DAO,我建议使用Springockito:https://bitbucket.org/kubek2k/springockito/wiki/Home
这里也提到: Injecting Mockito mocks into a 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;
在@Test或@Before Methode中,您可以使用标准的Mockito方式设置模拟:
Mockito.doReturn(null).when(mockedCountyDao).selectFromDB();
答案 2 :(得分:1)
好吧,静态方法MockitoAnnotations.initMocks(Object)
用于引导整个过程。
我不知道它是如何工作的,因为我没有浏览过源代码,但我会实现这样的:
Object
注释扫描传递的@Mock
的成员变量类。Object
注释扫描传递的@InjectMocks
的成员变量类。答案 3 :(得分:0)
没关系,在网上看 - InjectMocks注释将@Mock注释作为一个字段处理,并且是静态范围的(类范围的),所以我真的不能保证模拟会转到正确的服务。对于尝试在功能级而不是类级别进行单元测试而言,这有点像是一个思想实验。猜猜我会用Spring自动装配这些东西......