2012-11-13 5 views
27

Ich habe eine Webanwendung, wo ich das typische Problem habe, dass es verschiedene Konfigurationsdateien für verschiedene Umgebungen benötigt. Einige Konfigurationen werden auf dem Anwendungsserver als JNDI-Datenquellen gespeichert. Einige Konfigurationen bleiben jedoch in den Eigenschaftendateien erhalten.Federprofile und Testen

Daher möchte ich die Spring-Profile-Funktion verwenden.

Mein Problem ist, dass ich den Testfall nicht ausgeführt bekomme.

context.xml:

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

Testcase:

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

    @Test 
    public void testContext(){ 

    } 
} 

Das Problem, dass die Variable das Profil für das Laden zu sein scheint, ist nicht gelöst:

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 

Die aktuelle Profil sollte mit der @ActiveProfile Annotation 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 er ist (wenn möglich).

Wie kann ich das Profil richtig aktivieren? Ist es möglich, das Profil mit einer context.xml festzulegen? Kann ich die Variable in einer test-context.xml deklarieren, die den normalen Kontext aufruft?

Antwort

23

Kann ich empfehlen es auf diese Weise tun, definieren Sie Ihre Test wie folgt aus:

@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 folgendem Inhalt in myprops.properties Datei:

spring.profiles.active=localtest 

Mit dieser Ihre zweite Eigenschaftsdatei erhalten sollen, aufgelöst:

META-INF/spring/config_${spring.profiles.active}.properties 
+1

Dank. Abbildung eine Verbesserung hinzugefügt unten. –

+0

Dieser Ansatz ist nicht sauber, Sie müssen zu der Eigenschaftendatei gehen, in der der aktive Profilwert geändert werden soll. – codebusta

5

Mit Blick auf Bijus Antwort fand ich eine funktionierende Lösung.

hat er eine zusätzliche kontext Datei test-context.xml:

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

das Profil mit einem Gehalt:

spring.profiles.active=localtest 

und den Tests mit dem 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(){ 

    } 
} 

Diese etwas Arbeit sparen beim Erstellen mehrere Testfälle.

+0

Also jedes Mal, wenn Sie einen Test ausführen möchten, müssen Sie zu test-context.xml wechseln und den Pfad der Eigenschaftendatei ändern, wenn Sie eine andere Eigenschaft laden möchten? Es widerspricht der Idee von Spring Profiles. Sehen Sie sich in diesem Fall meine Lösung an. – codebusta

+0

@CodeBusta Nein, es ist eine test-context.xml nur für den Test, der auch den regulären Kontext lädt. –

2

Der beste Ansatz ist hier @ActiveProfiles Annotation und gehen Sie wie folgt zu entfernen:

@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 die folgenden:

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

Wenn Sie statische Eigenschaften verwenden, ohne dass diese in @AfterClass aufgeräumt werden, kann dies zu schwerwiegenden, schwer zu analysierenden Problemen führen. –

+0

Haben Sie noch weitere Vorschläge? Wenn Sie eine bessere Lösung haben, können Sie es hier einfügen. – codebusta

+2

Nun, wie gesagt: bereinigen Sie zumindest die Eigenschaften über System.clearProperty() in einer AfterClass-Methode. Oder benutze eine Regel wie https://stefanbirkner.github.io/system-rules/ –

Verwandte Themen