2012-08-29 56 views
3

我有我的抽象测试类的代码段(我知道XmlBeanFactoryClassPathResource已弃用,但它不太可能是问题的情况)。Spring测试@ContextConfiguration和静态上下文

@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?

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

回答

6

您是对的,您的代码将产生两个应用程序上下文:一个将由@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注释您的测试类,做清理工作在一些测试豆:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration 
@DirtiesContext(classMode = AFTER_CLASS) 
public abstract class AbstractIntegrationTest { 

    //... 

} 

public class OnlyForTestsBean { 

    @PreDestroy 
    public void willBeCalledAfterEachTestClassDuringShutdown() { 
     //.. 
    } 

} 
+0

关于第二选择。在所有测试之前运行一次并不是一个大问题。事情是,如何做课后*逻辑? – Vic

+0

@Vic:查看我的更新 –

+0

第一个解决方案仍然存在问题:“从* where *获取应用程序上下文注入?”第二个必须工作。我会尝试。 – Vic

5

不知道你是否选择了任何方法在这里,但我遇到了同样的问题,并用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(); 

    } 
} 

通过这样做,您可以访问应用程序上下文,做你的设置/用春豆在这里拆卸。

希望这有助于任何人尝试像我一样使用JUnit + Spring进行集成测试。

+0

感谢您的解决方案。据我所知,我确实选择了Tomasz的方法。 – Vic

相关问题