2012-11-13 24 views
27

Mam aplikację internetową, w której mam typowy problem, który wymaga różnych plików konfiguracyjnych dla różnych środowisk. Niektóre konfiguracje są umieszczane na serwerze aplikacji jako źródła danych JNDI, jednak niektóre konfiguracje pozostają w plikach właściwości.Profile sprężyn i testowanie

Dlatego chcę użyć funkcji Spring profiles.

Mój problem polega na tym, że nie mam uruchomionego testu.

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(){ 

    } 
} 

Problem wydaje się, że zmienna ładowania profil nie został rozwiązany:

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 

Prąd profil powinien być ustawiony za pomocą adnotacji @ActiveProfile. Ponieważ jest to sprawa testowa, nie będę mógł korzystać z web.xml. Jeśli to możliwe, chciałbym również uniknąć opcji środowiska wykonawczego. Test powinien przebiegać tak, jak jest (jeśli to możliwe).

Jak mogę właściwie aktywować profil? Czy można ustawić profil za pomocą pliku context.xml? Czy mogę zadeklarować zmienną w pliku test-context.xml, który faktycznie wywołuje normalny kontekst?

Odpowiedz

23

mogę polecić robi to w ten sposób, należy zdefiniować test tak:

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

    } 
} 

o następującej zawartości w pliku myprops.properties:

spring.profiles.active=localtest 

Z tego pliku drugie właściwości powinien dostać rozwiązany:

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

Dzięki. Wykreślono jedną poprawkę dodaną poniżej. –

+0

To podejście nie jest czyste, musisz przejść do pliku właściwości, w którym należy zmienić aktywną wartość profilu. – codebusta

5

Patrząc na odpowiedź Biju znalazłem działające rozwiązanie.

stworzyłem dodatkową kontekstowe plik test-context.xml:

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

zawierającego profil:

spring.profiles.active=localtest 

i załadunek test z:

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

    @Test 
    public void testContext(){ 

    } 
} 

Oszczędza to trochę pracy przy tworzeniu wiele przypadków testowych.

+0

Więc za każdym razem, gdy chcesz uruchomić test, musisz przejść do test-context.xml i zmienić ścieżkę pliku właściwości, jeśli chcesz załadować inną właściwość? Jest to sprzeczne z ideą profili wiosennych. Spójrz na moje rozwiązanie w tym przypadku. – codebusta

+0

@CodeBusta Nie, to test-context.xml tylko do testu, który ładuje również zwykły kontekst. –

2

Najlepszym rozwiązaniem jest, aby usunąć @ActiveProfiles adnotacji i wykonaj następujące czynności:

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

    } 
} 

A twój test-context.xml powinien posiadać:

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

Używanie właściwości statycznych bez ich czyszczenia w @AfterClass może prowadzić do poważnych, trudnych do analizy problemów. –

+0

Czy masz jakieś inne sugestie? Jeśli masz lepsze rozwiązanie, możesz je tutaj umieścić. – codebusta

+2

Cóż, jak już powiedziałem: przynajmniej wyczyść właściwości przez System.clearProperty() w metodzie AfterClass. Lub użyj jakiejś zasady, takiej jak https://stefanbirkner.github.io/system-rules/ –

Powiązane problemy