java - unitaria - Pruebas de integración de muelles con perfil.
software para pruebas unitarias en java (5)
En nuestras aplicaciones web de Spring, usamos los perfiles de bean de Spring para diferenciar tres escenarios: desarrollo, integración y producción. Los usamos para conectarnos con diferentes bases de datos o establecer otras constantes.
El uso de los perfiles de Spring Bean funciona muy bien para cambiar el entorno de la aplicación web.
El problema que tenemos es cuando nuestro código de prueba de integración necesita un cambio para el entorno. En estos casos, la prueba de integración carga el contexto de la aplicación de la aplicación web. De esta manera no tenemos que redefinir las conexiones de la base de datos, las constantes, etc. (aplicando el principio DRY).
Configuramos nuestras pruebas de integración como las siguientes.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = ["classpath:applicationContext.xml"])
public class MyTestIT
{
@Autowired
@Qualifier("myRemoteURL") // a value from the web-app''s applicationContext.xml
private String remoteURL;
...
}
Puedo hacer que se ejecute localmente utilizando @ActiveProfiles
, pero esto está codificado y hace que nuestras pruebas fallen en el servidor de compilación.
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = ["classpath:applicationContext.xml"])
@ActiveProfiles("development")
public class MyTestIT
{ ... }
También intenté usar @WebAppConfiguration
con la esperanza de que de alguna manera pudiera importar la propiedad spring.profiles.active
de Maven, pero eso no funciona.
Otra nota, también necesitamos configurar nuestro código para que los desarrolladores puedan ejecutar la aplicación web y luego ejecutar las pruebas utilizando el corredor de pruebas de IntelliJ (u otro IDE). Esto es mucho más fácil para depurar las pruebas de integración.
Como @ElderMael mencionó, usted podría usar la propiedad argLine del plugin maven surefire. A menudo, cuando necesito ejecutar todas las pruebas con diferentes perfiles Spring específicos, defino un perfil de Maven adicional. Ejemplo:
<profiles>
<profile>
<id>foo</id>
<dependencies>
<!-- additional dependencies if needed, i.e. database drivers ->
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<argLine>-Dspring.profiles.active=foo</argLine>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
Con ese enfoque, podría ejecutar fácilmente todas las pruebas con el perfil activado por el comando maven:
mvn clean test -Pfoo
La anotación de @ActiveProfile es buena, pero a veces necesitamos ejecutar toda la prueba con perfiles específicos activados y con los parámetros de @ActiveProfile codificados, es un problema.
Por ejemplo: por defecto, la prueba de integración con H2 en memoria db, pero a veces desea ejecutar la prueba en la base de datos "real". Usted podría definir ese perfil de Maven adicional y definir el trabajo de Jenkins. Con SpringBoot también puede poner propiedades adicionales para probar / recursos con el nombre application-foo.yml (o propiedades) y esas propiedades se tendrán en cuenta para.
Como otras personas ya han señalado, puede optar por usar Maven para establecer la propiedad del sistema spring.profiles.active
, asegurándose de no usar @ActiveProfiles
, pero eso no es conveniente para las pruebas que se ejecutan dentro del IDE.
Para un medio programático para establecer los perfiles activos, tiene algunas opciones.
- Spring 3.1: escriba un
ContextLoader
personalizado que prepare el contexto configurando perfiles activos en el entorno del contexto. - Spring 3.2: un
ContextLoader
personalizadoContextLoader
siendo una opción, pero una mejor opción es implementar unApplicationContextInitializer
y configurarlo a través del atributoinitializers
de@ContextConfiguration
. Su inicializador personalizado puede configurar elEnvironment
mediante la programación de los perfiles activos. - Primavera 4.0: las opciones antes mencionadas todavía existen; sin embargo, a partir de Spring Framework 4.0 hay una nueva API dedicada a
ActiveProfilesResolver
que se usa exactamente para este propósito: para determinar mediante programación el conjunto de perfiles activos para usar en una prueba. UnActiveProfilesResolver
se puede registrar a través del atributo deresolver
de@ActiveProfiles
.
Saludos,
Sam (autor del Spring TestContext Framework)
Hay muchas caras a este problema. en mi caso, una adición simple a build.gradle ya ayudó:
test { systemProperties = System.properties }
Si desea evitar la codificación rígida del perfil, puede utilizar la propiedad del sistema spring.profiles.active
y configurarlo para lo que necesite en ese entorno en particular, por ejemplo, tenemos los perfiles "dev", "stage" y "prod" para nuestros diferentes ambientes; también tenemos perfiles de "prueba", "prueba local" y "servidor de prueba" para nuestras pruebas.
Recuerde que puede tener más de un perfil en esa propiedad del sistema utilizando una lista de valores separados por comas, por ejemplo, "test, test-qa".
Puede especificar las propiedades del sistema en un proyecto de Maven en el plugin maven surefire o pasarlas así:
mvn -DargLine="-DpropertyName=propertyValue"
Tuve un problema similar: quería ejecutar todas mis pruebas de integración con un perfil predeterminado, pero permitir a un usuario anularlo con un perfil que representaba un entorno diferente o incluso una versión de DB sin tener que cambiar el valor de @ActiveProfiles. Esto es factible si está utilizando Spring 4.1+ con un ActiveProfilesResolver personalizado.
Este resolutor de ejemplo busca una propiedad del sistema, spring.profiles.active , y si no existe, delegará en el resolvedor predeterminado que simplemente usa la anotación @ActiveProfiles.
public class SystemPropertyActiveProfileResolver implements ActiveProfilesResolver {
private final DefaultActiveProfilesResolver defaultActiveProfilesResolver = new DefaultActiveProfilesResolver();
@Override
public String[] resolve(Class<?> testClass) {
if(System.getProperties().containsKey("spring.profiles.active")) {
final String profiles = System.getProperty("spring.profiles.active");
return profiles.split("//s*,//s*");
} else {
return defaultActiveProfilesResolver.resolve(testClass);
}
}
}
Y en tus clases de prueba, lo usarías así:
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles( profiles={"h2","xyz"},
resolver=SystemPropertyActiveProfileResolver.class)
public class MyTest { }
Por supuesto, puede usar otros métodos además de verificar la existencia de una propiedad del sistema para establecer los perfiles activos. Espero que esto ayude a alguien.