使用profile进行Spring集成测试

在我们的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)运行测试。 这对于调试集成测试来说要容易得多。

正如其他人已经指出的那样,您可以选择使用Maven来设置spring.profiles.active系统属性,确保使用@ActiveProfiles ,但这对于在IDE中运行的测试来说并不方便。

有关设置活动配置文件的编程方法,您有几个选项。

  1. Spring 3.1:编写一个自定义ContextLoader ,通过在上下文环境中设置活动配置文件来准备上下文。
  2. Spring 3.2:自定义ContextLoader仍然是一个选项,但更好的选择是实现ApplicationContextInitializer并通过@ContextConfigurationinitializers属性进行@ContextConfiguration 。 您的自定义初始化程序可以通过以编程方式设置活动配置文件来配置Environment
  3. Spring 4.0:上述选项仍然存在; 但是,从Spring Framework 4.0开始,有一个专门用于此目的的新的专用ActiveProfilesResolver API:以编程方式确定要在测试中使用的活动配置文件集。 可以通过@ActiveProfilesresolver属性注册ActiveProfilesResolver

问候,

Sam(Spring TestContext Framework的作者)

我遇到了类似的问题:我希望使用默认配置文件运行所有集成测试,但允许用户使用代表不同环境甚至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 { } 

除了检查是否存在系统属性以设置活动配置文件之外,您当然可以使用其他方法。 希望这有助于某人。

如果您想避免对配置文件进行硬编码,您可能需要使用系统属性 spring.profiles.active并将其设置为您在该特定环境中所需的任何内容,例如我们有“dev”,“stage”和“prod”配置文件我们不同的环境; 我们还有一个“测试”,“测试本地”和“测试服务器”配置文件供我们测试。

请记住,通过使用逗号分隔值列表(例如“test,test-qa”),您可以在该系统属性中拥有多个配置文件。

您可以在maven surefire插件中的maven项目中指定系统属性,或者像这样传递它们:

 mvn -DargLine="-DpropertyName=propertyValue" 

正如@ElderMael所提到的,你可以使用maven surefire插件的argLine属性。 通常当我需要使用不同的特定Spring配置文件运行所有测试时,我定义了额外的maven配置文件。 例:

   foo  

这个问题有很多面孔。 在我的例子中,build.gradle的一个简单的补充已经帮助:

 test { systemProperties = System.properties }