在我们的Spring Web应用程序中,我们使用Spring bean配置文件来区分三种场景:开发,集成和生产。我们使用它们连接到不同的数据库或设置其他常量。
使用Spring bean配置文件非常适合更改Web应用程序环境。
我们遇到的问题是我们的集成测试代码需要针对环境进行更改。在这些情况下,集成测试会加载Web应用程序的应用程序上下文。这样我们就不必重新定义数据库连接,常量等(应用DRY原则)。
我们设置如下的集成测试。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = ["classpath:applicationContext.xml"])
public class MyTestIT
{
@Autowired
@Qualifier("myRemoteURL") // a value from the web-app's applicationContext.xml
private String remoteURL;
...
}
我可以使用@ActiveProfiles
使其在本地运行,但这是硬编码的,导致我们的测试在构建服务器上失败。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = ["classpath:applicationContext.xml"])
@ActiveProfiles("development")
public class MyTestIT
{ ... }
我也尝试使用@WebAppConfiguration
希望它可能以某种方式从Maven导入spring.profiles.active
属性,但这不起作用。
另外需要注意的是,我们还需要配置代码,以便开发人员可以运行Web应用程序,然后使用IntelliJ的测试运行器(或其他IDE)运行测试。这对于调试集成测试来说要容易得多。
答案 0 :(得分:35)
正如其他人已经指出的那样,您可以选择使用Maven来设置spring.profiles.active
系统属性,确保不使用@ActiveProfiles
,但这不方便用于在IDE中运行的测试。
对于设置活动配置文件的程序化方法,您有几个选项。
ContextLoader
,通过在上下文Environment
中设置活动配置文件来准备上下文。ContextLoader
仍然是一个选项,但更好的选择是实施ApplicationContextInitializer
并通过initializers
@ContextConfiguration
属性对其进行配置。您的自定义初始值设定项可以通过以编程方式设置活动配置文件来配置Environment
。ActiveProfilesResolver
API:以编程方式确定要在测试中使用的活动配置文件集。 ActiveProfilesResolver
可以通过resolver
的{{1}}属性进行注册。此致
Sam(Spring TestContext Framework的作者)
答案 1 :(得分:15)
我遇到了类似的问题:我希望使用默认配置文件运行所有集成测试,但允许用户使用代表不同环境甚至db风格的配置文件覆盖,而无需更改@ActiveProfiles值。如果您使用Spring 4.1+和自定义ActiveProfilesResolver,这是可行的。
此示例解析程序查找系统属性 spring.profiles.active ,如果它不存在,它将委托给只使用@ActiveProfiles注释的默认解析程序。
public class SystemPropertyActiveProfileResolver implements ActiveProfilesResolver {
private final DefaultActiveProfilesResolver defaultActiveProfilesResolver = new DefaultActiveProfilesResolver();
@Override
public String[] resolve(Class<?> testClass) {
if(System.getProperties().containsKey("spring.profiles.active")) {
final String profiles = System.getProperty("spring.profiles.active");
return profiles.split("\\s*,\\s*");
} else {
return defaultActiveProfilesResolver.resolve(testClass);
}
}
}
在你的测试课程中,你会像这样使用它:
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles( profiles={"h2","xyz"},
resolver=SystemPropertyActiveProfileResolver.class)
public class MyTest { }
除了检查是否存在系统属性以设置活动配置文件之外,您当然可以使用其他方法。希望这有助于某人。
答案 2 :(得分:5)
如果您想避免对配置文件进行硬编码,可以使用system property spring.profiles.active
并将其设置为特定环境中您需要的内容,例如我们为不同的环境提供“dev”,“stage”和“prod”配置文件;我们还有一个“测试”,“测试本地”和“测试服务器”配置文件供我们测试。
请记住,通过使用以逗号分隔的值列表,您可以在该系统属性中拥有多个配置文件,例如“试验,试验-QA”。
您可以在maven surefire plugin中的maven项目中指定系统属性,或者像这样传递它们:
mvn -DargLine="-DpropertyName=propertyValue"
答案 3 :(得分:2)
正如@ElderMael所提到的,你可以使用maven surefire插件的argLine属性。通常当我需要使用不同的特定Spring配置文件运行所有测试时,我定义了额外的maven配置文件。例如:
<profiles>
<profile>
<id>foo</id>
<dependencies>
<!-- additional dependencies if needed, i.e. database drivers ->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dspring.profiles.active=foo</argLine>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
使用这种方法,您可以通过maven命令轻松地使用激活的配置文件运行所有测试:
mvn clean test -Pfoo
@ActiveProfile注释很好但有时我们需要使用激活的特定配置文件运行所有测试,并且使用硬编码的@ActiveProfile参数这是一个问题。
例如:默认情况下使用H2内存数据库进行集成测试,但有时你想在&#34;真实&#34;上运行测试。数据库。您可以定义其他maven配置文件并定义Jenkins作业。使用SpringBoot,您还可以使用名称application-foo.yml(或属性)为测试/资源添加其他属性,并将这些属性考虑在内。
答案 4 :(得分:-1)
这个问题有很多面孔。 在我的例子中,build.gradle的一个简单的补充已经有所帮助:
test { systemProperties = System.properties }