【发布时间】:2013-01-31 23:14:36
【问题描述】:
我正在开发一个同时具有组件和集成测试的应用程序。两者之间的区别是:组件测试测试多个类(即,它的内部对象并未全部模拟出来 - 但其中一些可能是 [例如 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) 标记集成测试,类中的第一个测试将失败,因为 SomeServiceInterface 被模拟 - 但下一个测试将通过,因为上下文已经刷新。
有趣的是:
如果我让 Spring 在集成测试中注入 SomeServiceInterface,它将注入 SomeServiceInterface 的具体实现——而不是模拟!
我已经尝试了很多方法来解决这个问题:
-
使用上下文中的 registerBeanDefinition 方法完成组件测试后,以编程方式覆盖上下文中的 bean
-
创建一个 TestExecution 侦听器,以便在执行 IntegrationTest 之前尝试手动刷新上下文
-
对不同的上下文使用相同的加载器......
-
这个故事一直在继续。
有人知道吗?
P.S.:我很理解采用 Springockito 是一个可疑的想法 - 但这个决定不是我做出的,现在我们在项目中有超过 500 个测试 - 因此重构它们以删除 Springockito 将是一项漫长的任务,因此它不是一个可行的选择 ATM。
【问题讨论】:
-
8 年后:请参阅 Spring Boot 的
@MockBean注释,它非常适合这个用例
标签: java spring testing mocking springockito