Spring Webアプリケーションでは、Spring Beanプロファイルを使用して、開発、統合、本番の3つのシナリオを区別します。これらを使用して、さまざまなデータベースに接続したり、他の定数を設定したりします。
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
{ ... }
また、Mavenから@WebAppConfiguration
プロパティをインポートすることを期待してspring.profiles.active
を使用しようとしましたが、これは機能しません。
もう1つの注意点として、開発者がWebアプリを実行し、IntelliJのテストランナー(または別のIDE)を使用してテストを実行できるようにコードを構成する必要もあります。これは、統合テストのデバッグがはるかに簡単です。
他の人がすでに指摘しているように、spring.profiles.active
システムプロパティを設定するためにMavenを使用することを選択できますnotが@ActiveProfiles
を使用することを確認しますが、テストの実行には不便ですIDE内。
プログラムによるアクティブプロファイルの設定方法には、いくつかのオプションがあります。
ContextLoader
にアクティブプロファイルを設定してコンテキストを準備するカスタムEnvironment
を記述します。ContextLoader
はオプションのままですが、ApplicationContextInitializer
を実装し、@ContextConfiguration
のinitializers
属性を介して構成することをお勧めします。カスタム初期化子は、アクティブなプロファイルをプログラムで設定することにより、Environment
を構成できます。ActiveProfilesResolver
APIが用意されています。これは、テストで使用するアクティブプロファイルのセットをプログラムで決定するためです。 ActiveProfilesResolver
は、@ActiveProfiles
のresolver
属性を介して登録できます。よろしく、
Sam(Spring TestContext Frameworkの作者)
同様の問題がありました。すべての統合テストをデフォルトのプロファイルで実行したいのですが、@ ActiveProfilesの値を変更せずに、ユーザーが別の環境またはdbフレーバーを表すプロファイルでオーバーライドできるようにしました。これは、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 { }
もちろん、システムプロパティの存在を確認する以外に、アクティブプロファイルを設定する他の方法を使用できます。これが誰かを助けることを願っています。
プロファイルのハードコーディングを避けたい場合は、 system propertyspring.profiles.active
を使用して、特定の環境で必要なものに設定します。さまざまな環境に対応する「dev」、「stage」、「prod」のプロファイルがあります。また、テスト用に「test」、「test-local」、「test-server」のプロファイルがあります。
カンマ区切り値のリストを使用して、そのシステムプロパティに複数のプロファイルを含めることができます。 「test、test-qa」。
maven surefire plugin でMavenプロジェクトのシステムプロパティを指定するか、次のように渡します。
mvn -DargLine="-DpropertyName=propertyValue"
@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インメモリdbとの統合テストですが、「実際の」データベースでテストを実行したい場合があります。その追加のMavenプロファイルを定義し、Jenkinsジョブを定義できます。 SpringBootを使用すると、application/foo.yml(またはプロパティ)という名前のtest/resourcesに追加のプロパティを追加することもでき、それらのプロパティが考慮されます。