我正在开发一个同时具有组件和集成测试的应用程序。之间的区别在于:组件测试测试不止一个类(即,它的内部对象都没有被模拟 - 但是其中一些可能是[如JMS发布者])并且集成测试是一个测试什么都没有被嘲笑。换句话说,Spring为您提供了对象,并按原样测试它。
到目前为止,非常好。
问题是:为了能够从Spring上下文中替换一个或多个依赖项,我使用了Springockito(https://bitbucket.org/kubek2k/springockito/wiki/Home),它为您提供了一种从Spring上下文中模拟掉一些bean的方法。
所以 - 在组件测试中 - 我有这个:
@RunWith(SpringJUnit4ClassRunner.class)
@DirtiesContext(classMode = AFTER_CLASS)
@ContextConfiguration(loader = SpringockitoContextLoader.class, locations = "classpath:spring-classify-test.xml")
public class....
@Autowired
@ReplaceWithMock
private SomeServiceInterface someServiceInterface;
@Autowired
private Bean bean;
Bean将SomeServiceInterface作为依赖。
public class Bean {
private SomeServiceInterface...
在上面的例子中,SomeServiceInterface将被mock替换。当然,这个例子是对问题的过度简化 - 我将bean替换为对象图中进一步向下依赖的模拟对象。
值得注意的是我从这个文件加载了上下文:spring-classify-test.xml同样,我注意到在执行类之后我将上下文标记为脏 - 所以, AFAIK,下一个测试类必须重新加载上下文。
好的,现在进行集成测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = SpringockitoContextLoader.class, locations = {"classpath:/spring-service-integration-test.xml" })
public class ...
@Autowired
private Bean bean;
我从spring-service-integration-test.xml加载上下文 - 但Bean内的SomeServiceInterface仍然被模拟!集成测试中使用的上下文也已更改!
如果我使用@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)标记Integration测试,则类中的第一个测试将失败,因为SomeServiceInterface被模拟 - 但下一个测试将通过,因为已经刷新了上下文。
有趣的是:
如果我要求Spring在Integration Test中注入SomeServiceInterface,它将注入一个SomeServiceInterface具体实现 - 而不是模拟!
我已经尝试了很多东西来解决这个问题:
1)在使用上下文中的registerBeanDefinition方法完成组件测试后,以编程方式覆盖上下文中的bean
2)创建一个TestExecution侦听器,这样我就可以尝试在执行IntegrationTest之前手动刷新上下文
3)对不同的上下文使用相同的加载器....
4)这个故事一直在继续。
有没有人有任何想法?
PS:我非常明白采用Springockito是一个可疑的想法 - 但这个决定不是我做的,现在我们在项目中有超过500个测试 - 因此重构它们以删除Springockito将是一个长期的任务,因此它不是一个可行的选择ATM。干杯。
答案 0 :(得分:1)
@DirtiesContext
注释在DirtiesContextTestExecutionListener注册时由TestContextManager处理。使用普通的Spring测试,默认情况下会注册该侦听器。也许Springockito或你的测试“组件测试”中的其他东西正在做一些干扰默认监听器注册的事情?
答案 1 :(得分:0)
我建议使用
尝试最新的springockito-annotations 1.0.8@DirtiesMocks(classMode = DirtiesMocks.ClassMode.AFTER_CLASS)