我的抽象测试类有以下代码(我知道XmlBeanFactory
ClassPathResource
已被弃用,但不太可能出现问题。)
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public abstract class AbstractIntegrationTest {
/** Spring context. */
protected static final BeanFactory context = new XmlBeanFactory(new ClassPathResource(
"com/.../AbstractIntegrationTest-context.xml"));
...
}
它加载默认的测试配置XML文件AbstractIntegrationTest-context.xml
(然后我使用自动装配)。我还需要在使用@BeforeClass
和@AfterClass
注释的静态方法中使用Spring,因此我有一个指向同一位置的单独上下文变量。但事实是,这是一个单独的上下文,它将具有不同的bean实例。那么如何合并这些上下文或如何从静态上下文中调用@ContextConfiguration
定义的Spring的bean初始化?
我想到了摆脱那些静态成员的可能解决方案,但我很好奇,如果我可以通过对代码进行相对较小的更改来做到这一点。
答案 0 :(得分:8)
您是对的,您的代码将生成两个应用程序上下文:一个将由@ContextConfiguration
注释为您启动,缓存和维护。您自己创建的第二个上下文。两者都没有多大意义。
不幸的是,JUnit不太适合集成测试 - 主要是因为你不能在类之前使用而在类非静态方法之后使用。我看到了两个选择:
切换到testng - 我知道这是一大步
仅在测试期间对上下文中包含的Spring bean中的设置/拆除逻辑进行编码 - 但在所有测试之前它只运行一次。
也有不太优雅的方法。您可以使用static
变量并为其注入上下文:
private static ApplicationContext context;
@AfterClass
public static afterClass() {
//here context is accessible
}
@Autowired
public void setApplicationContext(ApplicationContext applicationContext) {
context = applicationContext;
}
或者您可以使用@DirtiesContext
注释您的测试类,并在某个测试bean中进行清理:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@DirtiesContext(classMode = AFTER_CLASS)
public abstract class AbstractIntegrationTest {
//...
}
public class OnlyForTestsBean {
@PreDestroy
public void willBeCalledAfterEachTestClassDuringShutdown() {
//..
}
}
答案 1 :(得分:6)
不确定你是否在这里选择了任何方法,但我遇到了同样的问题并使用Spring测试框架TestExecutionListener
以另一种方式解决了这个问题。
有beforeTestClass
和afterTestClass
,因此在JUnit中都相当于@BeforeClass
和@AfterClass
。
我的方式:
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners(Cleanup.class)
@ContextConfiguration(locations = { "/integrationtest/rest_test_app_ctx.xml" })
public abstract class AbstractIntegrationTest {
// Start server for integration test.
}
您需要创建一个扩展AbstractTestExecutionListener的类:
public class Cleanup extends AbstractTestExecutionListener
{
@Override
public void afterTestClass(TestContext testContext) throws Exception
{
System.out.println("cleaning up now");
DomainService domainService=(DomainService)testContext.getApplicationContext().getBean("domainService");
domainService.delete();
}
}
通过这样做,您可以访问应用程序上下文,并使用spring beans进行设置/拆卸。
希望这有助于任何人尝试像我一样使用JUnit + Spring进行集成测试。