我需要在我的测试类的单个方法中更改我的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
支持用于测试的活动配置文件的声明性配置(通过value
和profiles
属性)和编程配置(通过resolver
属性),但仅支持测试类级别(不在方法级别)。另一个选择是实现ApplicationContextInitializer
并通过@ContextConfiguration(initializers=...)
配置它。
在刷新之前影响ApplicationContext
的唯一另一种方法是实现SmartContextLoader
或扩展其中一个提供的类并通过@ContextConfiguration(loader=...)
配置它。例如,AbstractGenericContextLoader.customizeContext()
允许“在将bean定义加载到上下文之后但在刷新上下文之前”自定义由加载器创建的GenericApplicationContext
。
最好的祝福,
Sam(Spring TestContext Framework的作者)
并非所有应用程序上下文都支持多个refresh
。根据AbstractRefreshableApplicationContext
的javadoc,只有它或AbstractRefreshableWebApplicationContext
的子类不止一次接受refresh
而且GenericApplicationContext
不是其中之一。
您应该为ApplicationContext
使用另一个类来支持热刷新。
编辑:
当您使用@ContextConfiguration
注释时,您应该使用自定义ContextLoader
或SmartContextLoader
实现来强制spring使用较少的傻瓜ApplicationContext
。但我从来没有找到一个干净利落的方式。因此,当我在测试类中需要XmlWebApplicationContext
时,我不使用@ContextConfiguration
,而是在@Before
方法或测试开始时手动创建和刷新我的上下文。
我知道这并没有真正回答你的问题,但你可以将其视为一种解决方法。
有一个很好的小黑客触发上下文刷新 - 使用org.springframework.cloud.context.refresh.ContextRefresher
。
我不是100%肯定这个方法会适合你:它需要一个spring-cloud-context
依赖。但是,这可能会像test
依赖项一样添加,而不会泄漏到生产类路径中。
要使用这个刷新器,你还需要导入org.springframework.cloud.autoconfigure.RefreshAutoConfiguration
配置,它将RefreshScope
范围添加到你的applicationContext
,它实际上是在引擎盖下完成工作。
所以,修改测试如下:
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.autoconfigure.RefreshAutoConfiguration;
import org.springframework.cloud.context.refresh.ContextRefresher;
// your other imports
@WebAppConfiguration
@ContextConfiguration(locations = {"/web/WEB-INF/spring.xml"}, classes = RefreshAutoConfiguration.class)
@ActiveProfiles(resolver = BaseActiveProfilesResolverTest.class)
public class ControllerTest extends AbstractTestNGSpringContextTests {
@Autowired
private ContextRefresher contextRefresher;
@Test
public void test() throws Exception {
// doSmth before
contextRefresher.refresh();
// context is refreshed - continue testing
}
}