Jak ustawić zmienną środowiskową lub właściwość systemową w testach wiosennych?

95

Chciałbym napisać kilka testów, które sprawdzą konfigurację XML Spring wdrożonej WAR. Niestety, niektóre ziarna wymagają ustawienia pewnych zmiennych środowiskowych lub właściwości systemu. Jak ustawić zmienną środowiskową przed zainicjowaniem fasolek wiosennych, używając wygodnego stylu testowego z @ContextConfiguration?

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
public class TestWarSpringContext { ... }

Jeśli skonfiguruję kontekst aplikacji z adnotacjami, nie widzę zaczepu, w którym mogę coś zrobić przed zainicjowaniem kontekstu sprężynowego.

Hans-Peter Störr
źródło

Odpowiedzi:

127

Możesz zainicjować właściwość System w inicjatorze statycznym:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
public class TestWarSpringContext {

    static {
        System.setProperty("myproperty", "foo");
    }

}

Statyczny kod inicjujący zostanie wykonany przed zainicjowaniem kontekstu aplikacji Spring.

Jimmy Praet
źródło
14
Głupi ja - OK, to zadziała. Jeszcze lepiej: prawdopodobnie @BeforeClassmetoda ustawiania właściwości systemu i @AfterClassmetoda jej usuwania również zadziała i ładnie posprząta po sobie. (Jednak nie wypróbowałem tego.)
Hans-Peter Störr
1
Wypróbowałem @BeforeClass - i działało dobrze przy ustawianiu właściwości systemu, zanim inne właściwości zostały ustawione w instancji testowej
wbdarby
Dzięki za to. Statyczna rzecz nie działała, ale działała mała metoda z @BeforeClass!
Midhun Agnihotram
Ten mechanizm nie działa w przypadku zmiany właściwości pliku konfiguracyjnego Log4j2. Wygląda na to, że Spring i tak jest ładowany (a więc rejestrowany nieprawidłowo) przed tym statycznym fragmentem kodu.
lucasvc
87

Właściwym sposobem, aby to zrobić, począwszy od Spring 4.1, jest użycie @TestPropertySourceadnotacji.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:whereever/context.xml")
@TestPropertySource(properties = {"myproperty = foo"})
public class TestWarSpringContext {
    ...    
}

Zobacz @TestPropertySource w dokumentacji Spring i Javadocs .

Ramana
źródło
2
Ta adnotacja obsługuje również ścieżkę do pliku właściwości.
MigDus
2
Mogłem zmienić etykietę Spring Cloud Config Client podczas testów przy użyciu@TestPropertySource(properties={"spring.cloud.config.label=feature/branch"})
Marcello de Sales
5
Dobra odpowiedź, ale niestety nie działała dla mnie, używając Spring 4.2.9, nieruchomość była zawsze pusta. Działał tylko blok statyczny ... Pracował dla właściwości aplikacji, ale nie dla właściwości systemowych.
Gregor,
Najpierw zobaczyłem i wypróbowałem wersję statyczną (która działała), ale ta adnotacja jest jeszcze czystsza i znacznie bardziej preferowana (dla mnie, ponieważ działa również jak urok).
BAERUS
4
Zapewnia to Environmentwłaściwość, która różni się od „zmiennej środowiskowej”.
OrangeDog
11

Można także użyć testowego ApplicationContextInitializer do zainicjowania właściwości systemowej:

public class TestApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>
{
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext)
    {
        System.setProperty("myproperty", "value");
    }
}

a następnie skonfiguruj go w klasie testowej oprócz lokalizacji pliku konfiguracji kontekstu Spring:

@ContextConfiguration(initializers = TestApplicationContextInitializer.class, locations = "classpath:whereever/context.xml", ...)
@RunWith(SpringJUnit4ClassRunner.class)
public class SomeTest
{
...
}

W ten sposób można uniknąć duplikowania kodu, jeśli dla wszystkich testów jednostkowych należy ustawić określoną właściwość systemu.

anre
źródło
Działa to również doskonale z Spring Boot 2.x i Junit 5.x (używając @SpringBootTestlub dowolnej adnotacji testowej wycinania )
Wim Deblauwe
11

Wszystkie odpowiedzi tutaj dotyczą obecnie tylko właściwości systemu, które różnią się od zmiennych środowiskowych, które są bardziej złożone, szczególnie. do testów. Na szczęście można do tego użyć poniżej klasy, a dokumentacja klasy ma dobre przykłady

EnvironmentVariables.html

Szybki przykład z dokumentacji, zmodyfikowany do pracy z @SpringBootTest

@SpringBootTest
public class EnvironmentVariablesTest {
   @ClassRule
   public final EnvironmentVariables environmentVariables = new EnvironmentVariables().set("name", "value");

   @Test
   public void test() {
     assertEquals("value", System.getenv("name"));
   }
 }
Harish Gokavarapu
źródło
Reguły EnvironmentVariables są częścią biblioteki innej firmy, używają hacky refleksji do zmiany buforowanych wartości środowiska w pamięci maszyny JVM i nie uwzględniają nawet rzeczywistych zmiennych środowiskowych. Dlatego nie chciałbym go używać ani nikomu nie polecać.
Christian,
4

Jeśli chcesz, aby twoje zmienne były ważne dla wszystkich testów, możesz mieć application.propertiesplik w katalogu zasobów testowych (domyślnie:), src/test/resourcesktóry będzie wyglądał mniej więcej tak:

MYPROPERTY=foo

Zostanie on następnie załadowany i użyty, chyba że masz definicje za pomocą @TestPropertySourcelub podobnej metody - dokładną kolejność ładowania właściwości można znaleźć w rozdziale 24 dokumentacji sprężyny . Konfiguracja zewnętrzna .

blalasaadri
źródło
2

Możesz ustawić właściwości systemu jako argumenty maszyny wirtualnej.

Jeśli twój projekt jest projektem maven, możesz wykonać następujące polecenie podczas uruchamiania klasy testowej:

mvn test -Dapp.url="https://stackoverflow.com"

Klasa testu:

public class AppTest  {
@Test
public void testUrl() {
    System.out.println(System.getProperty("app.url"));
    }
}

Jeśli chcesz uruchomić indywidualną klasę testową lub metodę w eclipse, to:

1) Przejdź do Uruchom -> Uruchom konfigurację

2) Po lewej stronie wybierz klasę testu w sekcji Junit.

3) wykonaj następujące czynności:

wprowadź opis obrazu tutaj

Joby Wilson Mathews
źródło
2

W przypadku testów jednostkowych wystąpienie zmiennej systemowej nie jest jeszcze tworzone, gdy wykonuję „czystą instalację mvn”, ponieważ nie ma serwera, na którym działa aplikacja. Aby ustawić właściwości systemu, muszę to zrobić w pom.xml. Tak jak to:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-surefire-plugin</artifactId>
    <version>2.21.0</version>
    <configuration>
        <systemPropertyVariables>
            <propertyName>propertyValue</propertyName>
            <MY_ENV_VAR>newValue</MY_ENV_VAR>
            <ENV_TARGET>olqa</ENV_TARGET>
            <buildDirectory>${project.build.directory}</buildDirectory>
        </systemPropertyVariables>
    </configuration>
</plugin>
Gen
źródło