web-dev-qa-db-ja.com

春のプロファイルとテスト

さまざまな環境に応じてさまざまな構成ファイルを必要とするという典型的な問題があるWebアプリケーションがあります。一部の構成はJNDIデータソースとしてアプリケーションサーバーに配置されますが、一部の構成はプロパティファイルに残ります。

したがって、Springプロファイル機能を使用したいと思います。

私の問題は、テストケースが実行されないことです。

context.xml:

<context:property-placeholder 
  location="classpath:META-INF/spring/config_${spring.profiles.active}.properties"/>

テスト:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
    TestPreperationExecutionListener.class
    })
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration(locations = {
    "classpath:context.xml" })
public class TestContext {

  @Test
  public void testContext(){

  }
}

問題は、プロファイルをロードするための変数が解決されていないことです。

Caused by: Java.io.FileNotFoundException: class path resource [META-INF/spring/config_${spring.profiles.active}.properties] cannot be opened because it does not exist
at org.springframework.core.io.ClassPathResource.getInputStream(ClassPathResource.Java:157)
at org.springframework.core.io.support.PropertiesLoaderSupport.loadProperties(PropertiesLoaderSupport.Java:181)
at org.springframework.core.io.support.PropertiesLoaderSupport.mergeProperties(PropertiesLoaderSupport.Java:161)
at org.springframework.context.support.PropertySourcesPlaceholderConfigurer.postProcessBeanFactory(PropertySourcesPlaceholderConfigurer.Java:138)
... 31 more

現在のプロファイルは、@ActiveProfileアノテーションで設定する必要があります。テストケースなので、web.xmlを使用することはできません。可能であれば、ランタイムオプションも回避したいと思います。テストはそのまま実行する必要があります(可能な場合)。

プロファイルを適切に有効化するにはどうすればよいですか? context.xmlを使用してプロファイルを設定することは可能ですか?実際に通常のコンテキストを呼び出しているtest-context.xmlで変数を宣言できますか?

41
Udo Held

この方法でこれを行うことをお勧めします。テストを次のように定義します。

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
    TestPreperationExecutionListener.class
    })
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration
public class TestContext {

  @Test
  public void testContext(){

  }

  @Configuration
  @PropertySource("classpath:/myprops.properties")
  @ImportResource({"classpath:context.xml" })
  public static class MyContextConfiguration{

  }
}

myprops.propertiesファイルに次のコンテンツが含まれます。

spring.profiles.active=localtest

これにより、2番目のプロパティファイルが解決されます。

META-INF/spring/config_${spring.profiles.active}.properties
41
Biju Kunjummen

Bijuの答えを見て、実用的な解決策を見つけました。

追加のコンテキストファイルtest-context.xmlを作成しました。

<context:property-placeholder location="classpath:config/spring-test.properties"/>

プロファイルを含む:

spring.profiles.active=localtest

そして、テストをロードする:

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
    TestPreperationExecutionListener.class
    })
@Transactional
@ActiveProfiles(profiles = "localtest")
@ContextConfiguration(locations = {
    "classpath:config/test-context.xml" })
public class TestContext {

  @Test
  public void testContext(){

  }
}

これにより、複数のテストケースを作成する際の作業が節約されます。

6
Udo Held

ここでの最善のアプローチは、@ ActiveProfilesアノテーションを削除して、次のことを行うことです。

@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({
    TestPreperationExecutionListener.class
    })
@Transactional
@ContextConfiguration(locations = {
    "classpath:config/test-context.xml" })
public class TestContext {

  @BeforeClass
  public static void setSystemProperty() {
        Properties properties = System.getProperties();
        properties.setProperty("spring.profiles.active", "localtest");
  }

  @AfterClass
  public static void unsetSystemProperty() {
        System.clearProperty("spring.profiles.active");
  }

  @Test
  public void testContext(){

  }
}

また、test-context.xmlには次のものが必要です。

<context:property-placeholder 
  location="classpath:META-INF/spring/config_${spring.profiles.active}.properties"/>
2
codebusta
public class LoginTest extends BaseTest {
    @Test
    public void exampleTest( ){ 
        // Test
    }
}

基本テストクラスから継承します(この例はtestngではなくjUnitですが、ActiveProfilesは同じです):

@ContextConfiguration(locations = { "classpath:spring-test-config.xml" })
@ActiveProfiles(resolver = MyActiveProfileResolver.class)
public class BaseTest extends AbstractTestNGSpringContextTests { }

MyActiveProfileResolverには、使用するプロファイルを決定するために必要なロジックを含めることができます。

public class MyActiveProfileResolver implements ActiveProfilesResolver {
    @Override
    public String[] resolve(Class<?> aClass) {
        // This can contain any custom logic to determine which profiles to use
        return new String[] { "exampleProfile" };
    }
}

これにより、テストに必要な依存関係を解決するために使用されるプロファイルが設定されます。

1
psych