Spring测试@ContextConfiguration和静态上下文

时间:2012-08-29 16:31:19

标签: spring junit

我的抽象测试类有以下代码(我知道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初始化?

我想到了摆脱那些静态成员的可能解决方案,但我很好奇,如果我可以通过对代码进行相对较小的更改来做到这一点。

2 个答案:

答案 0 :(得分:8)

您是对的,您的代码将生成两个应用程序上下文:一个将由@ContextConfiguration注释为您启动,缓存和维护。您自己创建的第二个上下文。两者都没有多大意义。

不幸的是,JUnit不太适合集成测试 - 主要是因为你不能在类之前使用而在类非静态方法之后使用。我看到了两个选择:

  • 切换到 - 我知道这是一大步

  • 仅在测试期间对上下文中包含的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以另一种方式解决了这个问题。

beforeTestClassafterTestClass,因此在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进行集成测试。