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.
GO TO FULL VERSION