Runner de JUnit 4 en Spring
Spring TestContext Framework ofrece integración completa con JUnit 4 a través de un corredor dedicado (compatible con
JUnit 4.12 o superior). Al marcar las clases de prueba con la anotación @RunWith(SpringJUnit4ClassRunner.class)
,
o la anotación más corta @RunWith(SpringRunner.class)
, los
desarrolladores pueden implementar pruebas unitarias y de integración estándar basadas en JUnit 4 mientras
aprovechan los beneficios del marco TestContext, como soporte para cargar contextos de aplicaciones, inyección de
dependencia en instancias de prueba, ejecución transaccional de métodos de prueba, etc. Si necesita utilizar Spring
TestContext Framework con un ejecutor alternativo (como el ejecutor Parameterized
de JUnit 4) o
ejecutores de terceros (como MockitoJUnitRunner
), puede opcionalmente, use las funciones de soporte de
reglas JUnit de Spring.
La siguiente lista de código muestra los requisitos mínimos para configurar una clase
de prueba para ejecutar usando un Runner
personalizado en Spring:
@RunWith(SpringRunner.class)
@TestExecutionListeners({})
public class SimpleTest {
@Test
public void testMethod() {
// lógica de prueba...
}
}
@RunWith(SpringRunner::class)
@TestExecutionListeners
class SimpleTest {
@Test
fun testMethod() {
// lógica de prueba...
}
}
En el ejemplo anterior, la anotación @TestExecutionListeners
está configurada con una lista vacía
para deshabilitar los oyentes de forma predeterminada que, de otro modo, requerirían configurar ApplicationContext
a través de la anotación @ContextConfiguration
.
Spring JUnit 4 reglas
El paquete org.springframework.test.context.junit4.rules
proporciona las siguientes
reglas de JUnit 4 (compatibles con JUnit 4.12 o superior):
SpringClassRule
SpringMethodRule
SpringClassRule
es el TestRule
de JUnit que admite funciones de Spring TestContext
Framework a nivel de clase, y SpringMethodRule
es el MethodRule
de JUnit que admite
características a nivel de instancia y método de Spring TestContext Framework.
A diferencia de SpringRunner
,
la ventaja del soporte JUnit basado en reglas de Spring es que es independiente de cualquier implementación de
org.junit.runner.Runner
y, por lo tanto, se puede combinar con corredores alternativos existentes
(como Parameterized
de JUnit 4) o corredores de terceros (como MockitoJUnitRunner
).
Para admitir la funcionalidad completa del marco TestContext, debe combinar SpringClassRule
con SpringMethodRule
.
El siguiente ejemplo muestra la forma correcta de declarar estas reglas en una prueba de integración:
// Opcionalmente, especifique un corredor que no sea Spring's Runner a través de @RunWith(...)
@ContextConfiguration
public class IntegrationTest {
@ClassRule
public static final SpringClassRule springClassRule = new SpringClassRule();
@Rule
public final SpringMethodRule springMethodRule = new SpringMethodRule();
@Test
public void testMethod() {
// lógica de prueba...
}
}
// Opcionalmente, configuramos un corredor que no es un Spring Runner a través de @RunWith(...)
@ContextConfiguration
class IntegrationTest {
@Rule
val springMethodRule = SpringMethodRule()
@Test
fun testMethod() {
// lógica de prueba...
}
companion object {
@ClassRule
val springClassRule = SpringClassRule()
}
}
Clases auxiliares de JUnit 4
El paquete org.springframework.test.context.junit4
proporciona las siguientes clases auxiliares para casos de prueba basados en JUnit 4 (compatibles con JUnit 4.12 o
superior):
AbstractJUnit4SpringContextTests
AbstractTransactionalJUnit4SpringContextTests
AbstractJUnit4SpringContextTests
es una clase de prueba base abstracta que integra Spring
TestContext Framework con soporte explícito de prueba ApplicationContext
en el framework JUnit 4. Si
extiende AbstractJUnit4SpringContextTests
, puede acceder a la variable de instancia
protected
de applicationContext
, que se puede utilizar para realizar búsquedas explícitas
de beans o para probar el estado del contexto en su conjunto.
AbstractTransactionalJUnit4SpringContextTests
es una extensión transaccional abstracta de
AbstractJUnit4SpringContextTests
que agrega algunas características convenientes para acceder a JDBC.
Esta clase espera que
ApplicationContext
tenga definidos un bean javax.sql.DataSource
y un bean PlatformTransactionManager
.
Si extiende
AbstractTransactionalJUnit4SpringContextTests
, puede acceder a la variable de instancia
protected
jdbcTemplate
, que puede usar para ejecutar sentencias SQL para consultar los datos de la base de datos.
Puede utilizar dichas consultas para validar el estado de la base de datos antes y después de ejecutar el código de
la aplicación asociado con la base de datos, y Spring garantiza que dichas consultas se ejecuten dentro de la misma
transacción que el código de la aplicación. Cuando se utiliza junto con una herramienta ORM, se deben evitar los
falsos
positivos. Como se menciona en la sección Soporte de pruebas de JDBC, AbstractTransactionalJUnit4SpringContextTests
también proporciona métodos auxiliares que delegan autoridad a los métodos en
JdbcTestUtils
utilizando el
jdbcTemplate
mencionado anteriormente. Además,
AbstractTransactionalJUnit4SpringContextTests
proporciona el método
executeSqlScript(..)
para ejecutar scripts SQL en el DataSource
configurado.
@ RunWith(SpringRunner.class)
o reglas JUnit para Spring.
SpringExtension para JUnit Jupiter
Spring TestContext
Framework ofrece un marco completo integración con el marco de pruebas JUnit Jupiter introducido en JUnit 5. Al
anotar las clases de prueba con @ExtendWith(SpringExtension.class)
, puede implementar pruebas unitarias
y de integración estándar sobre JUnit Jupiter mientras aprovecha las ventajas de beneficios del marco TestContext,
como soporte para cargar contextos de aplicaciones, inyección de dependencias en instancias de prueba, ejecución
transaccional de métodos de prueba, etc.
Además, gracias a la rica extensión API en JUnit Jupiter, Spring proporciona la siguientes capacidades además de ese conjunto de características que Spring admite para JUnit 4 y TestNG:
Inyección de dependencia para constructores de prueba, métodos de prueba y métodos de devolución de llamada del ciclo de vida de prueba. Consulte Inyección de dependencia con
SpringExtension
para obtener más información.Soporte completo para ejecución condicional de pruebasbasadas en expresiones SpEL, variables de entorno, propiedades del sistema, etc. Para obtener más información y ejemplos, consulte la documentación de las anotaciones
@EnabledIf
y@DisabledIf
en "Anotaciones de JUnit Jupiter para pruebas en Spring".Anotaciones compuestas especiales que combinan anotaciones de Spring y JUnit Jupiter. Para obtener más información, consulte los ejemplos de anotaciones
@TransactionalDevTestConfig
y@TransactionalIntegrationTest
en "Soporte para meta anotaciones para pruebas".
La siguiente lista de código muestra cómo configurar una clase de prueba para usar
SpringExtension
en combinación con @ContextConfiguration
:
// Le ordenamos a JUnit Jupiter que extienda la prueba con soporte de Spring
@ExtendWith(SpringExtension.class)
// Indique a Spring que cargue ApplicationContext desde TestConfig.class
@ContextConfiguration(classes = TestConfig.class)
class SimpleTests {
@Test void testMethod() {
// lógica de prueba...
}
}
// Le ordenamos a JUnit Jupiter que extienda la prueba con soporte de Spring.
@ExtendWith(SpringExtension::class)
// Indique a Spring que cargue ApplicationContext desde TestConfig.class
@ContextConfiguration(classes = [TestConfig::class])
class SimpleTests {
@Test
fun testMethod() {
// lógica de prueba...
}
}
Dado que JUnit 5 también puede usar anotaciones como metaanotaciones, Spring proporciona anotaciones
compuestas @SpringJUnitConfig
y @SpringJUnitWebConfig
para simplificar la configuración
de la prueba ApplicationContext
y JUnit Jupiter.
El siguiente ejemplo utiliza la anotación
@SpringJUnitConfig
para reducir la cantidad de configuración utilizada en el ejemplo anterior:
// Le indica a Spring que registre SpringExtension con JUnit
// Jupiter y cargue ApplicationContext desde TestConfig.class
@SpringJUnitConfig(TestConfig.class)
class SimpleTests {
@Test
void testMethod() {
// lógica de prueba...
}
}
// Le indica a Spring que registre un SpringExtension con JUnit
// Jupiter y cargue el ApplicationContext desde TestConfig.class
@SpringJUnitConfig(TestConfig::class)
class SimpleTests {
@Test
fun testMethod() {
// lógica de prueba...
}
}
De manera similar, el siguiente ejemplo utiliza la anotación @SpringJUnitWebConfig
para crear un
WebApplicationContext
para su uso. con JUnit Júpiter:
// Le indica a Spring que registre SpringExtension con JUnit
// Jupiter y cargue WebApplicationContext desde TestWebConfig.class
@SpringJUnitWebConfig(TestWebConfig.class)
class SimpleWebTests {
@Test
void testMethod() {
// lógica de prueba...
}
}
// Le indica a Spring que registre SpringExtension con JUnit
// Jupiter y cargue WebApplicationContext desde TestWebConfig::class
@SpringJUnitWebConfig(TestWebConfig::class)
class SimpleWebTests {
@Test
fun testMethod() {
// lógica de prueba...
}
}
Para obtener más información, consulte la documentación de @SpringJUnitConfig
y @SpringJUnitWebConfig
en "Anotaciones de JUnit
Jupiter para pruebas en Spring".
La inyección de dependencia utilizando SpringExtension
SpringExtension
implementa la extensión API ParameterResolver
de JUnit Jupiter, que permite a Spring proporcionar
inyección de dependencia para constructores de pruebas, métodos de prueba y devolución de llamada del ciclo de vida
de pruebas métodos.
En particular, SpringExtension
puede inyectar dependencias de una prueba
ApplicationContext
en constructores de pruebas y métodos anotados con @BeforeAll
. ,
@AfterAll
, @BeforeEach
, @AfterEach
, @Test
,
@RepeatedTest
, @ParameterizedTest
y otras anotaciones.
Inyección de dependencia a través del constructor
Si un determinado parámetro en un constructor de clase de prueba de JUnit Jupiter es de tipo
ApplicationContext
(o un subtipo del mismo) o anotado o metaanotado con @Autowired
, @Qualifier
o
@Value
,
Spring inyecta el valor de este parámetro utilizando el correspondiente bean o valor de la prueba ApplicationContext
.
Spring también se puede configurar para detectar y vincular automáticamente todos los argumentos al constructor de una clase de prueba si el constructor se considera autoenlazable. . Un constructor se considera autowired si una de las siguientes condiciones es verdadera (en orden de precedencia).
El constructor está anotado con
@Autowired
.La anotación
@TestConstructor
está presente o metapresente para una clase de prueba con el atributoautowireMode
establecido enALL
.El modo de enlace y detección del constructor de pruebas predeterminado se ha cambiado a
ALL
.
Más información sobre el uso de @TestConstructor
anotación y para cambiar el modo de enlace y detección automática del Test Constructor global,
consulte la sección sobre la anotación @TestConstructor
.
ParameterResolver
registrado con JUnit Jupiter puede resolver parámetros para dicho
constructor.
Dependencias del constructor de inyección para clases de prueba no
se puede usar junto con el soporte de anotación @TestInstance(PER_CLASS)
de JUnit Jupiter si la
anotación @DirtiesContext
se usa para cerrar el código de prueba ApplicationContext
antes o después de los métodos de prueba.
La razón es que la anotación @TestInstance(PER_CLASS)
le dice a JUnit Jupiter que almacene en
caché la instancia de prueba entre llamadas al método de prueba. Por lo tanto, la instancia de prueba
conservará las referencias a los beans inyectados originalmente desde un ApplicationContext
que
se cerró posteriormente. Debido a que el constructor de la clase de prueba solo se llamará una vez en tales
escenarios, la inyección de dependencia no se repetirá y las pruebas posteriores interactuarán con beans del
ApplicationContext
privado, lo que puede generar errores.
Para utilizar la anotación @DirtiesContext
en el modo "antes del método de prueba" o "después
del método de prueba" en combinación con la anotación @TestInstance(PER_CLASS)
, debe Es
necesario configurar las dependencias de Spring para recibirlas inyectándolas a través de un campo o
definidor para que puedan reinyectarse entre llamadas al método de prueba.
En el siguiente ejemplo, Spring inyecta OrderService
bean del ApplicationContext
cargado desde TestConfig.class
en el constructor OrderServiceIntegrationTests
.
@SpringJUnitConfig(TestConfig .class)
class OrderServiceIntegrationTests {
private final OrderService orderService;
@Autowired OrderServiceIntegrationTests(OrderService orderService) {
this.orderService = orderService;
}
// pruebas utilizando el OrderService incorporado
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests @Autowired constructor(private val orderService: OrderService){
// pruebas que utilizan el OrderService integrado
}
Tenga en cuenta que esta función permite que las dependencias de prueba sean final
y por lo tanto
inmutable.
Si la propiedad spring.test.constructor.autowire.mode
es all
(ver
@TestConstructor
), puede omitir la declaración de la anotación @Autowired
para el
constructor del ejemplo anterior, lo que da como resultado lo siguiente.
@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {
private final OrderService orderService;
OrderServiceIntegrationTests(OrderService orderService) {
this.orderService = orderService;
}
// pruebas utilizando el OrderService incorporado
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests(val orderService:OrderService) {
// pruebas utilizando el OrderService integrado
}
Inyección de dependencia mediante método
Si el parámetro de un método de prueba de JUnit Jupiter o un método de devolución de llamada Es vital que el
bucle de prueba sea del tipo ApplicationContext
(o un subtipo del mismo) o esté anotado o
metaanotado con @Autowired
, @Qualifier
o anotaciones @Value
, Spring
inyecta el valor para ese parámetro en particular usando el bean correspondiente de la prueba ApplicationContext
.
En el siguiente ejemplo, Spring inyecta el OrderService
de ApplicationContext
cargado
desde TestConfig.class
en el método de prueba deleteOrder()
:
@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {
@Test
void deleteOrder(@Autowired OrderService orderService) {
// use orderService del ApplicationContext de la prueba
}
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests {
@Test
fun deleteOrder(@Autowired orderService: OrderService) {
// usa orderService desde el ApplicationContext de la prueba
}
}
Gracias al sólido soporte ParameterResolver
de JUnit Jupiter, se pueden crear múltiples
dependencias. Inyectado en un método, no solo desde Spring, sino también desde JUnit Júpiter u otras extensiones
de terceros.
El siguiente ejemplo muestra cómo hacer que Spring y JUnit Júpiter inyecten simultáneamente dependencias en
placeOrderRepeatedly()
método de prueba.
@SpringJUnitConfig(TestConfig.class)
class OrderServiceIntegrationTests {
@RepeatedTest(10)
void placeOrderRepeatedly(RepetitionInfo repeatedInfo,
@Autowired OrderService orderService) {
// use orderService del ApplicationContext de la prueba
// y repetitionInfo de JUnit Jupiter
}
}
@SpringJUnitConfig(TestConfig::class)
class OrderServiceIntegrationTests {
@RepeatedTest (10)
fun placeOrderRepeatedly(repetitionInfo:RepetitionInfo, @Autowired orderService:OrderService) {
// use orderService del ApplicationContext de la prueba
// y repetitionInfo de JUnit Jupiter
}
}
Tenga en cuenta que el uso de la anotación @RepeatedTest
de JUnit Jupiter permite que el método de
prueba acceda a RepetitionInfo
.
Configuración de clase de prueba con @Nested
Spring TestContext Framework admite el uso de anotaciones relacionadas con pruebas para clases de
prueba marcadas con la anotación @Nested
, en JUnit Jupiter desde Spring Framework 5.0; sin embargo,
antes de Spring Framework 5.3, las anotaciones de configuración de prueba a nivel de clase no se
heredaban de las clases anidadas, como es el caso de las superclases.
Spring Framework 5.3 introdujo soporte con todas las funciones para heredar la configuración de la clase de
prueba de las clases anidadas, y esta configuración se heredará de forma predeterminada. Para cambiar el modo
INHERIT
predeterminado al modo OVERRIDE
, puede marcar una única clase de prueba
anotada con @Nested
con @NestedTestConfiguration(EnclosingConfiguration.OVERRIDE)
.
Se aplicará una declaración @NestedTestConfiguration
explícita a la clase de prueba anotada, así
como a todas sus subclases y clases anidadas. Por lo tanto, es posible anotar una clase de prueba de alto nivel
con la anotación @NestedTestConfiguration
, y esto se aplicará a todas sus clases de prueba anidadas
de forma recursiva.
Para permitir a los equipos de desarrollo para cambiar el valor predeterminado a OVERRIDE
- por
ejemplo, para garantizar la compatibilidad con las versiones 5.0-5.2 de Spring Framework - el modo
predeterminado se puede cambiar globalmente a través de una propiedad del sistema JVM o un spring.properties
archivo en la raíz del classpath. Para obtener más información, consulte la nota "Cambiar
el modo de herencia de configuración envolvente predeterminado".
Aunque el siguiente ejemplo
"Hola mundo" es muy simplificado, muestra cómo declarar la configuración de una clase de alto nivel heredada por
sus
clases de prueba, marcada con la anotación @Nested
. En este ejemplo particular, solo se hereda la
clase
de configuración TestConfig
. Cada clase de prueba anidada expone su propio conjunto de perfiles
activos, lo que da como resultado un ApplicationContext
independiente para cada clase de prueba
anidada
(consulte para obtener más detalles "Contexto de almacenamiento
en caché"). Consulte la lista
de anotaciones
admitidas para ver qué anotaciones se pueden heredar en las clases de prueba con el <
annotation@Nested
.
@SpringJUnitConfig(TestConfig.class)
class GreetingServiceTests {
@Nested
@ActiveProfiles("lang_en")
class EnglishGreetings {
@Test
void hello(@Autowired GreetingService service) {
assertThat(service.greetWorld()).isEqualTo("Hello World");
}
}
@Nested
@ActiveProfiles("lang_de")
class GermanGreetings {
@Test
void hello(@Autowired GreetingService service) {
assertThat(service.greetWorld()).isEqualTo("Hallo Welt");
}
}
}
@SpringJUnitConfig(TestConfig::class)
class GreetingServiceTests {
@Nested
@ActiveProfiles("lang_en")
inner class EnglishGreetings {
@Test
fun hello(@Autowired service:GreetingService) {
assertThat(service.greetWorld()).isEqualTo("Hello World")
}
}
@Nested
@ActiveProfiles("lang_de")
inner class GermanGreetings {
@Test
fun hello(@Autowired service:GreetingService) {
assertThat(service.greetWorld()).isEqualTo("Hallo Welt")
}
}
}
Clases auxiliares de TestNG
El paquete org.springframework.test.context.testng
proporciona las siguientes clases auxiliares para
casos de prueba basados en TestNG:
AbstractTestNGSpringContextTests
AbstractTransactionalTestNGSpringContextTests
AbstractTestNGS SpringContextTests
es una clase de prueba base abstracta que integra Spring
TestContext Framework con soporte explícito para las pruebas de ApplicationContext en el marco TestNG. Si
extiende AbstractTestNGSpringContextTests, puede acceder a una variable de instancia de applicationContext
protegida que se puede utilizar para realizar una búsqueda explícita de BIN o para probar el estado del contexto
en su conjunto.
AbstractTransactionalTestNGSpringContextTests
es una extensión transaccional abstracta AbstractTestNGSpringContextTests
que agrega algunas características convenientes para acceder a JDBC. Esta clase espera que ApplicationContext
tenga definidos un bean javax.sql.DataSource
y un bean PlatformTransactionManager
. Si
extiende AbstractTransactionalTestNGSpringContextTests
, puede acceder a la variable de instancia
protected
jdbcTemplate
, que puede usar para ejecutar sentencias SQL para consultar los
datos de la base de datos. Puede utilizar dichas consultas para validar el estado de la base de datos antes y
después de ejecutar el código de la aplicación asociado con la base de datos, y Spring garantiza que dichas
consultas se ejecuten dentro de la misma transacción que el código de la aplicación. Cuando se utiliza junto con
una herramienta ORM, se deben evitar los falsos
positivos. Como se menciona en la sección Soporte de pruebas de JDBC, AbstractTransactionalTestNGSpringContextTests
también proporciona métodos auxiliares que delegan autoridad a los métodos en JdbcTestUtils
utilizando el jdbcTemplate
antes mencionado. Además, AbstractTransactionalTestNGSpringContextTests
proporciona el método executeSqlScript(..)
para ejecutar scripts SQL en el DataSource
configurado.
@ContextConfiguration
, @TestExecutionListeners
y etc., y
también instrumentar manualmente su clase de prueba usando TestContextManager
. Consulte el código
fuente de AbstractTestNGSpringContextTests
para ver un ejemplo de cómo puede instrumentar su clase
de prueba.