¿Cómo configurar la variable de entorno o la propiedad del sistema en las pruebas de primavera?

93

Me gustaría escribir algunas pruebas que verifiquen la configuración XML Spring de un WAR implementado. Desafortunadamente, algunos beans requieren que se establezcan algunas variables de entorno o propiedades del sistema. ¿Cómo puedo configurar una variable de entorno antes de que se inicialicen los beans de primavera cuando utilizo el estilo de prueba conveniente con @ContextConfiguration?

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

Si configuro el contexto de la aplicación con anotaciones, no veo un gancho en el que pueda hacer algo antes de que se inicialice el contexto de primavera.

Hans-Peter Störr
fuente

Respuestas:

127

Puede inicializar la propiedad del sistema en un inicializador estático:

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

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

}

El código del inicializador estático se ejecutará antes de que se inicialice el contexto de la aplicación Spring.

Jimmy Praet
fuente
14
Tonto de mí, está bien, eso funcionaría. Aún mejor: probablemente un @BeforeClassmétodo para establecer la propiedad del sistema y un @AfterClassmétodo para eliminarlo también funcionaría, y se limpiaría muy bien después de sí mismo. (Sin embargo, no lo probé)
Hans-Peter Störr
1
Probé @BeforeClass, y funcionó bien para configurar las propiedades del sistema antes de que se establecieran otras propiedades en la instancia de prueba
wbdarby
Gracias por esto. ¡Lo estático no funcionó, pero un pequeño método con @BeforeClass funcionó!
Midhun Agnihotram
Este mecanismo no funciona si se cambia la propiedad del archivo de configuración Log4j2. Parece que Spring de todos modos se está cargando (y por lo tanto registrando incorrectamente) antes de esa pieza de código estático.
lucasvc
86

La forma correcta de hacer esto, comenzando con Spring 4.1, es usar una @TestPropertySourceanotación.

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

Vea @TestPropertySource en Spring docs y Javadocs .

Raman
fuente
2
Esta anotación también admite una ruta de archivo de propiedades.
MigDus
2
Podría cambiar la etiqueta del cliente Spring Cloud Config durante las pruebas usando@TestPropertySource(properties={"spring.cloud.config.label=feature/branch"})
Marcello de Sales
4
Buena respuesta, pero lamentablemente no funcionó para mí, usando Spring 4.2.9, la propiedad siempre estaba vacía. Solo funcionó el bloque estático ... Funcionó para las propiedades de la aplicación, pero no para las propiedades del sistema.
Gregor
Primero vi y probé la versión estática (que funcionó), pero esta Anotación es aún más limpia y mucho más preferible (para mí, ya que también funciona de maravilla).
BAERUS
3
Esto proporciona una Environmentpropiedad, que es diferente a una "Variable de entorno".
OrangeDog
11

También se puede usar un ApplicationContextInitializer de prueba para inicializar una propiedad del sistema:

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

y luego configúrelo en la clase de prueba además de las ubicaciones del archivo de configuración de contexto de Spring:

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

De esta manera, se puede evitar la duplicación de código si se debe establecer una determinada propiedad del sistema para todas las pruebas unitarias.

anre
fuente
Esto también funciona perfectamente con Spring Boot 2.xy Junit 5.x (usando @SpringBootTesto cualquiera de las anotaciones de corte de prueba )
Wim Deblauwe
11

Todas las respuestas aquí actualmente solo hablan sobre las propiedades del sistema que son diferentes de las variables de entorno que son más complejas de configurar, especialmente. para pruebas. Afortunadamente, la clase a continuación se puede usar para eso y los documentos de la clase tienen buenos ejemplos

EnvironmentVariables.html

Un ejemplo rápido de los documentos, modificado para trabajar con @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
fuente
Las reglas de EnvironmentVariables son parte de una biblioteca de terceros, utiliza la reflexión hacky para cambiar los valores almacenados en caché del entorno en la memoria JVM y ni siquiera las variables de entorno reales. Entonces, no me gustaría usarlo ni recomendar a nadie que lo haga.
Christian
4

Si desea que sus variables sean válidas para todas las pruebas, puede tener un application.propertiesarchivo en su directorio de recursos de prueba (por defecto :) src/test/resourcesque se verá así:

MYPROPERTY=foo

Esto luego se cargará y usará a menos que tenga definiciones a través de @TestPropertySourceo un método similar; el orden exacto en el que se cargan las propiedades se puede encontrar en el capítulo 24 de la documentación de Spring . Configuración externa .

blalasaadri
fuente
2

Puede establecer las propiedades del sistema como argumentos de máquina virtual.

Si su proyecto es un proyecto experto, puede ejecutar el siguiente comando mientras ejecuta la clase de prueba:

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

Clase de prueba:

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

Si desea ejecutar una clase o método de prueba individual en eclipse, entonces:

1) Vaya a Ejecutar -> Ejecutar configuración

2) En el lado izquierdo, seleccione su clase de prueba en la sección Junit.

3) haz lo siguiente:

ingrese la descripción de la imagen aquí

Joby Wilson Mathews
fuente
2

Para las pruebas unitarias, la variable del sistema aún no se crea una instancia cuando hago "mvn clean install" porque no hay ningún servidor que ejecute la aplicación. Entonces, para configurar las propiedades del sistema, necesito hacerlo en pom.xml. Al igual que:

<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>
Gene
fuente