Anular la configuración predeterminada de la aplicación Spring-Boot.properties en Junit Test

198

Tengo una aplicación Spring-Boot donde las propiedades predeterminadas se establecen en un application.propertiesarchivo en el classpath (src / main / resources / application.properties).

Me gustaría anular algunas configuraciones predeterminadas en mi prueba JUnit con propiedades declaradas en un test.propertiesarchivo (src / test / resources / test.properties)

Normalmente tengo una clase de configuración dedicada para mis pruebas Junit, por ejemplo

package foo.bar.test;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

}

Primero pensé que usar @PropertySource("classpath:test.properties")en la clase TestConfig haría el truco, pero estas propiedades no sobrescribirán la configuración de application.properties (ver Spring-Boot Reference Doc - 23. Configuración externalizada ).

Luego traté de usar -Dspring.config.location=classpath:test.propertiesal invocar la prueba. Eso fue exitoso, pero no quiero establecer esta propiedad del sistema para cada ejecución de prueba. Así lo puse en el código

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

  static {
    System.setProperty("spring.config.location", "classpath:test.properties");
  }

}

que desafortunadamente nuevamente no tuvo éxito.

Debe haber una solución simple sobre cómo anular la application.propertiesconfiguración en las pruebas JUnit con la test.propertiesque debo haber pasado por alto.

FrVaBe
fuente
Si necesita configurar solo algunas propiedades, puede usar la nueva anotación @DynamicPropertySource. stackoverflow.com/a/60941845/8650621
Felipe Desiderati

Respuestas:

293

Puede usar @TestPropertySourcepara anular valores en application.properties. De su javadoc:

Las fuentes de propiedades de prueba se pueden usar para anular selectivamente las propiedades definidas en las fuentes de propiedades del sistema y de la aplicación

Por ejemplo:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class ExampleApplicationTests {

}
Andy Wilkinson
fuente
2
Eso es. Gracias. Desafortunadamente, no funciona cuando se usa en ExampleApplication.class, por lo que tengo que configurarlo en cada clase de prueba. ¿Está bien?
Viernes
1
Tiene que ir a algún lugar de la jerarquía de la clase de prueba, es decir, podría usar una superclase común para configurarla en varias clases de prueba diferentes.
Andy Wilkinson
64
También tenga en cuenta que @TestPropertySourcepuede aceptar un propertiesargumento para sobrescribir alguna propiedad en línea, por ejemplo @TestPropertySource(properties = "myConf.myProp=valueInTest"), es útil en caso de que no desee un archivo de propiedad totalmente nuevo.
dyng
2
Puede especificar varios archivos en una matriz y también archivos en el sistema de archivos (pero recuerde que podrían no funcionar en el servidor CI):@TestPropertySource(locations={"file:C:/dev/...","classpath:test.properties"})
Adam
8
Tenga en cuenta que eso @SpringApplicationConfigurationya está en desuso, y debe usar@SpringBootTest
mrkernelpanic el
74

Spring Boot se carga automáticamente src/test/resources/application.properties, si se utilizan las siguientes anotaciones

@RunWith(SpringRunner.class)
@SpringBootTest

Por lo tanto, cambie el nombre test.propertiesa application.propertiespara utilizar la configuración automática.

Si * solo * necesita cargar el archivo de propiedades (en el Entorno) también puede usar lo siguiente, como se explica aquí

@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) 

[ Actualización: anulación de ciertas propiedades para la prueba ]

  1. Añadir src/main/resources/application-test.properties .
  2. Anote la clase de prueba con @ActiveProfiles("test").

Esto carga application.propertiesy luego application-test.properties propiedades en el contexto de la aplicación para el caso de prueba, según las reglas definidas aquí .

Demostración: https://github.com/mohnish82/so-spring-boot-testprops

Mohnish
fuente
1
No estoy seguro de si es una buena idea tener dos application.propertiesarchivos en el classpath (uno adentro src/main/resourcesy uno adentro src/test/resources). ¿Quién garantiza que se tomarán ambos y cuál se tomará primero?
Viernes
3
¡@FrVaBe Spring lo garantizará! Las propiedades del perfil principal siempre se cargan. Luego, durante la fase de prueba, se cargan las propiedades de prueba, agregando / anulando propiedades nuevas / existentes. Si no lo hace como mantener dos archivos con el mismo nombre, a continuación, se puede añadir application-test.propertiesen src/main/resourcesy especificar testcomo el perfil activo en el caso de prueba.
Mohnish
77
La primavera no da una garantía. La herramienta de compilación utilizará los recursos de prueba en favor de los recursos principales durante las pruebas. Pero en el caso de una prueba application.properties, se ignorarán las application.properties principales. Eso no es lo que quiero porque el principal contiene varios valores predeterminados útiles y solo necesito anular algunos de ellos durante la prueba (y no quiero duplicar todo el archivo en la sección de prueba). Ver aquí .
Viernes
66
Tienes razón, solo las propiedades definidas en src/test/resources/application.propertiesse cargan durante la fase de prueba, src/main/resources/application.propertiesse ignora.
Mohnish
11
Si no utiliza perfiles hasta el momento, no necesita un perfil de "prueba" dedicado. Simplemente asigne un nombre a sus propiedades de prueba application-default.propertiesy se considerarán porque está ejecutando automáticamente el perfil "predeterminado" (si no se declara otro).
Viernes
65

También puede usar metaanotaciones para externalizar la configuración. Por ejemplo:

@RunWith(SpringJUnit4ClassRunner.class)
@DefaultTestAnnotations
public class ExampleApplicationTests { 
   ...
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public @interface DefaultTestAnnotations { }
Rob Winch
fuente
21

Otro enfoque adecuado para anular algunas propiedades en su prueba, si está utilizando una @SpringBootTestanotación:

@SpringBootTest(properties = {"propA=valueA", "propB=valueB"})
NimaAJ
fuente
1
Cómo SpringBootTestcarga el archivo application.properties?
TuGordoBello
8

TLDR:

Entonces, lo que hice fue tener el estándar src/main/resources/application.propertiesy también unsrc/test/resources/application-default.properties donde anulo algunas configuraciones para TODAS mis pruebas.

Toda la historia

Me encontré con el mismo problema y hasta ahora no estaba usando perfiles. Parecía molesto tener que hacerlo ahora y recordar haber declarado el perfil, lo cual se puede olvidar fácilmente.

El truco consiste en aprovechar que un perfil específico application-<profile>.propertiesanula la configuración en el perfil general. Ver https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-properties .

elonderin
fuente
3

Explicación simple:

Si usted es como yo y que tienen el mismo application.propertiesen src/main/resourcesy src/test/resources, y usted está preguntando por qué el application.propertiesen la carpeta de prueba no se preponderantes con elapplication.properties de sus principales recursos, sigue leyendo ...

Si tiene application.propertiesdebajo src/main/resourcesy el mismo application.propertiesdebajo src/test/resources, que application.propertiesse recoge, depende de cómo esté ejecutando sus pruebas . La carpeta de la estructura src/main/resources y src/test/resources, es una convención de arquitectura Maven, por lo que si se ejecuta la prueba como mvnw testo incluso gradlew test, la application.propertiesde src/test/resourcesconseguirá recogido, como prueba de ruta de clase precederá principal ruta de clase. Sin embargo, si se ejecuta la prueba como Run as JUnit Testen el Elipse / STS, la application.propertiesde src/main/resourcesconseguirá recogido, como principales precede classpath prueba de ruta de clases.

Puedes verlo abriendo el Run > Run Configurations > JUnit > *your_run_configuration* > Click on "Show Command Line" .

Verás algo como:

XXXbin \ javaw.exe -ea -Dfile.encoding = UTF-8 -classpath XXX \ workspace-spring-tool-suite-4-4.5.1.RELEASE \ project_name \ bin \ main; XXX \ workspace-spring-tool-suite-4-4.5.1.RELEASE \ nombre_proyecto \ bin \ test;

¿Ves que \ main viene primero, y luego \ test ? Bien, se trata de classpath :-)

Salud

jumping_monkey
fuente
1
I just configured min as the following :

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console


# changing the name of my data base for testing
spring.datasource.url= jdbc:h2:mem:mockedDB
spring.datasource.username=sa
spring.datasource.password=sa



# in testing i don`t need to know the port

#Feature that determines what happens when no accessors are found for a type
#(and there are no annotations to indicate it is meant to be serialized).
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false`enter code here`
Hilal Aissani
fuente
1

Si está utilizando Spring 5.2.5 y Spring Boot 2.2.6 y desea anular solo algunas propiedades en lugar de todo el archivo. Puede usar la nueva anotación: @DynamicPropertySource

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }
}
Felipe Desiderati
fuente
0

De lo contrario, podemos cambiar el nombre del configurador de propiedades predeterminado, establecer la propiedad spring.config.name=testy luego tener un recurso class-path de src/test/test.propertiesnuestra instancia nativa org.springframework.boot.SpringApplicationse configurará automáticamente a partir de este test.properties separado, ignorando las propiedades de la aplicación;

Ventaja: autoconfiguración de pruebas;

Inconveniente: exponer la propiedad "spring.config.name" en la capa CI

ref: http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html

spring.config.name = aplicación # Nombre del archivo de configuración

D. Soloviev
fuente
55
Ignorar application.propertiesno es una opción para mí, ya que solo quiero anular algunos de los valores de configuración originales en la prueba.
Viernes
He estado buscando una manera de tener una sola prueba que no cargue src / main / resources / application.properties y esta es la siguiente. Cree un archivo: src / test / resources / empty.properties y agregue la anotación a las pruebas que deberían ignorar las propiedades principales. @TestPropertySource (propiedades = "spring.config.name = empty")
rvertigo
¿Cómo establecer un valor de propiedad específico para cada método de prueba junit?
Nicolas
0

También puede crear un archivo application.properties en src / test / resources donde se escriben sus JUnits.

Fuego pragmático
fuente
¿Cómo ayuda esto? ^^
jumping_monkey