在测试方法中重新加载或刷新Spring应用程序上下文?

我需要在我的测试类的单个方法中更改我的applicationContext中活动的Spring配置文件,为此我需要在刷新竞赛之前运行一行代码,因为我使用的是ProfileResolver。 我尝试过以下方法:

@WebAppConfiguration @ContextConfiguration(locations = {"/web/WEB-INF/spring.xml"}) @ActiveProfiles(resolver = BaseActiveProfilesResolverTest.class) public class ControllerTest extends AbstractTestNGSpringContextTests { @Test public void test() throws Exception { codeToSetActiveProfiles(...); ((ConfigurableApplicationContext)this.applicationContext).refresh(); ... tests here ... codeToSetActiveProfiles(... back to prior profiles ...); ... ideally refresh/reload the context for future tests } } 

但我得到:

 java.lang.IllegalStateException: GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once 

DirtiesContext对我来说不起作用,因为它是在类/方法执行之后运行,而不是之前,我需要在运行刷新/重新加载之前执行一行代码。

有什么建议么? 我试着看一下正在运行的监听器/钩子,但是我没有看到一个明显的位置来插入自己以实现这种行为。

按照设计,Spring TestContext Framework不会明确支持ApplicationContext编程刷新。 此外,测试方法并不打算刷新上下文。

因此,我建议您重新评估是否需要刷新,并考虑在专用测试类中放置需要不同活动配置文件集的测试方法等替代方案。

总之, @ActiveProfiles支持用于测试的活动配置文件的声明性配置(通过valueprofiles属性)和编程配置(通过resolver属性),但仅支持测试类级别(不在方法级别)。 另一种选择是实现ApplicationContextInitializer并通过@ContextConfiguration(initializers=...)

在刷新之前影响ApplicationContext的唯一另一种方法是实现SmartContextLoader或扩展其中一个提供的类,并通过@ContextConfiguration(loader=...)对其进行配置。 例如, AbstractGenericContextLoader.customizeContext()允许“ 在将 bean定义加载到上下文之后但刷新上下文之前 ”自定义由加载器创建的GenericApplicationContext

最好的祝福,

Sam(Spring TestContext Framework的作者)

并非所有应用程序上下文都支持多次refresh 。 根据用于AbstractRefreshableApplicationContext javadoc,只有它或AbstractRefreshableApplicationContext子类接受refresh多次…而GenericApplicationContext不是其中之一。

您应该为ApplicationContext使用另一个类来支持热刷新。

编辑:

当您使用@ContextConfiguration批注时,您应该使用自定义ContextLoaderSmartContextLoader实现来强制spring使用不那么愚蠢的ApplicationContext 。 但我从来没有找到一个干净利落的方式。 因此,当我在测试类中需要@ContextConfiguration ,我不使用@ContextConfiguration而是在@Before方法或测试开始时手动创建和刷新我的上下文。

我知道这并没有真正回答你的问题,但你可以将其视为一种解决方法。