我正在开发一个同时具有组件和集成测试的应用程序。两者之间的区别在于:组件测试测试多个类(即,它的内部对象并未全部模拟出来 - 但其中一些可能是 [例如 JMS 发布者]),而集成测试是一种测试一切都被嘲笑了。换句话说,Spring 为您提供了对象,然后您按原样对其进行测试。
到目前为止,一切都很好。
问题是:为了能够从 Spring 上下文中替换一个或另一个依赖项,我使用了 Springockito ( https://bitbucket.org/kubek2k/springockito/wiki/Home ),它为您提供了一种模拟一些 bean 的方法来自 Spring 上下文。
所以 - 在组件测试中 - 我有这个:
@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 将被模拟替换。当然,这个例子是对问题的过度简化——我用模拟对象替换了 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) 标记集成测试,则类中的第一个测试将失败,因为 SomeServiceInterface 被模拟 - 但下一个测试将通过,因为上下文已经刷新。
有趣的是:
如果我要求 Spring 在集成测试中注入 SomeServiceInterface,它将注入 SomeServiceInterface 的具体实现——而不是模拟!
我已经尝试了很多方法来解决这个问题:
使用上下文中的 registerBeanDefinition 方法完成组件测试后,以编程方式覆盖上下文中的 bean
创建一个 TestExecution 侦听器,以便我可以在执行 IntegrationTest 之前尝试手动刷新上下文
对不同的上下文使用相同的加载器......
这个故事一直在继续。
有人有什么主意吗?
PS:我很理解采用 Springockito 是一个可疑的想法 - 但这个决定不是我做出的,现在我们在项目中有超过 500 个测试 - 因此重构它们以删除 Springockito 将是一项漫长的任务,因此它不是可行的期权 ATM。