it-swarm.com.de

Federprofile und Prüfung

Ich habe eine Webanwendung, bei der ich das typische Problem habe, dass unterschiedliche Konfigurationsdateien für verschiedene Umgebungen erforderlich sind. Einige Konfigurationen werden als JNDI-Datenquellen auf dem Anwendungsserver abgelegt, einige Konfigurationen verbleiben jedoch in Eigenschaftsdateien.

Daher möchte ich die Funktion Federprofile verwenden.

Mein Problem ist, dass ich den Testfall nicht zum Laufen bekomme.

context.xml:

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

Testfall:

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

  @Test
  public void testContext(){

  }
}

Das Problem scheint zu sein, dass die Variable zum Laden des Profils nicht aufgelöst wird:

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

Das aktuelle Profil sollte mit der Annotation @ActiveProfile festgelegt werden. Da es sich um einen Testfall handelt, kann ich den web.xml nicht verwenden. Wenn möglich, möchte ich auch Laufzeitoptionen vermeiden. Der Test sollte so laufen, wie es ist (wenn möglich).

Wie kann ich das Profil richtig aktivieren? Kann das Profil mit einer context.xml festgelegt werden? Kann ich die Variable in einer test-context.xml deklarieren, die den normalen Kontext aufruft?

37
Udo Held

Kann ich empfehlen, es so zu machen, definieren Sie Ihren Test so:

@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{

  }
}

mit dem folgenden Inhalt in der Datei myprops.properties:

spring.profiles.active=localtest

Damit sollte Ihre zweite Eigenschaftsdatei aufgelöst werden:

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

Als ich Bijus Antwort sah, fand ich eine funktionierende Lösung.

Ich habe eine zusätzliche Kontextdatei erstellt test-context.xml:

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

Das Profil enthält:

spring.profiles.active=localtest

Und den Test mit laden:

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

  @Test
  public void testContext(){

  }
}

Dies erspart einige Arbeit beim Erstellen mehrerer Testfälle.

5
Udo Held

Die beste Methode ist, @ActiveProfiles Annotation zu entfernen und folgende Schritte auszuführen:

@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 setSystemProperty() {
        System.clearProperty("spring.profiles.active");
  }

  @Test
  public void testContext(){

  }
}

Und Ihre test-context.xml sollte folgendes haben:

<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
    }
}

Vererbt sich aus einer Basistestklasse (dieses Beispiel ist testng und nicht jUnit, aber die ActiveProfiles ist gleich):

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

MyActiveProfileResolver kann jede Logik enthalten, die zur Bestimmung des zu verwendenden Profils erforderlich ist: 

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" };
    }
}

Dadurch wird das Profil festgelegt, das dann zum Auflösen der vom Test erforderlichen Abhängigkeiten verwendet wird.

0
psych