Introducción
Contenido
- 1 Introducción
- 2 Anotaciones de prueba de Spring
- 3 @BootstrapCon
- 4 @ContextConfiguration
- 5 @WebAppConfiguration
- 6 @ContextHierarchy
- 7 @ActiveProfiles
- 8 @Rollback
- 9 @Commit
- 10 @BeforeTransaction
- 11 @AfterTransaction
- 12 @Sql
- 13 @SqlGroup
- 14 @SqlConfig
- 15 @SpringBootTest
- 16 @DataJpaTest
- 17 @DataMongoTest
- 18 @WebMvcTest
- 19 @MockBean
- 20 @AutoConfigureMockMvc
- 21 @JsonTest
- 22 @TestPropertySource
- 23 @Timed
- 24 @Repeat
- 25 Conclusión
Spring Framework es un marco muy robusto, lanzado en 2002. Sus características principales se pueden aplicar a aplicaciones Java simples o ampliarse a aplicaciones web modernas y complejas.
Dado que se actualiza constantemente y sigue nuevos paradigmas de arquitectura y programación, ofrece soporte para muchos otros marcos que trabajan de la mano con él.
Con una gama tan amplia de funcionalidades, es normal que nos presente algunas anotaciones nuevas, que son una parte clave del desarrollo de aplicaciones Spring.
La configuración de Spring es totalmente personalizable, lo que originalmente se hizo a través de archivos de configuración XML. Sin embargo, este enfoque se ha vuelto obsoleto y la mayoría de las personas hoy en día recurren a la configuración de anotaciones.
Dicho esto, esta serie de artículos tiene como objetivo desentrañar las opciones que usted, como desarrollador, tiene para configurar y usar el marco Spring:
- Anotaciones de Spring: @RequestMapping y sus variantes
- Spring Annotations: anotaciones de Core Framework
- Notas de Spring: Spring Cloud
- Spring Annotations: Prueba de anotaciones
Anotaciones de prueba de Spring
El desarrollo basado en pruebas (TDD) se ha convertido en un tema importante hoy en día y se considera una práctica extremadamente mala no probar correctamente sus aplicaciones.
Hay varios marcos de trabajo ampliamente utilizados que facilitan mucho este trabajo a los desarrolladores, donde JUnit es el más utilizado.
Para ponerse al día con las prácticas de programación modernas, Spring ha lanzado una nueva starter
dependencia spring-boot-starter-test
, que consta de algunos marcos:
- JUnit
- Prueba de Spring y prueba de arranque de Spring
- AssertJ
- Hamcrest
- Mockito
- JSONassert
- JsonPath
En este artículo, cubriremos las siguientes anotaciones de prueba:
- @BootstrapCon
- @ContextConfiguration
- @WebAppConfiguration
- @ContextHierarchy
- @ActiveProfiles
- @Retroceder
- @Cometer
- @AntesTransacciones
- @Después de la transacción
- @Sql
- @SqlGrupo
- @SqlConfig
- @SpringBootTest
- @DataJpaTest
- @DataMongoTest
- @WebMvcTest
- @MockBean
- @AutoConfigureMockMvc
- @JsonTest
- @TestPropertySource
- @Con tiempo
- @Repetir
@BootstrapCon
La @BootstrapWith
anotación es una anotación que probablemente utilizará muy raramente. Las configuraciones predeterminadas para Spring TestContext Framework son más que suficientes para la mayoría de los casos de uso.
Si no es así, puede cambiar ContextLoader
o implementar TestContext
s personalizados entre una gran cantidad de otras configuraciones que puede cambiar.
Nuevamente, esta es una anotación que probablemente no usará si no es parte de un equipo que realmente necesita una configuración personalizada para Spring TestContext Framework.
@ContextConfiguration
Una @ContextConfiguration
anotación de prueba de integración aplicada a nivel de clase que se usa para definir cómo Spring debe cargar el ApplicationContext
.
Esta anotación se puede aplicar junto con el @Component
(así como las anotaciones tales como @Service
, @Repository
, etc.) y @Configuration
anotaciones así como cualquier clase que contiene @Bean
s.
Puede utilizar la anotación para hacer referencia a archivos XML o clases Java:
@ContextConfiguration("/some-test-configuration-file.xml")
// @ContetConfiguration(locations = "/some-test-configuration-file.xml")
// You can use the optional `locations` flag as well.
public class ApplicationTests {
// Testing code...
}
@ContextConfiguration(classes = TestConfiguration.class)
public class ApplicationTests {
// Testing code...
}
Por ejemplo, digamos que tenemos TestBean
:
@Configuration
public class TestBean {
@Bean
public DeveloperService developerService() {
return new DeveloperService();
}
}
Si quisiéramos hacer algunos assert
s en este bean, haríamos algo como:
@ContextConfiguration(classes = TestBean.class)
public class ApplicationTests {
@Autowired
private DeveloperService;
@Test
public void testBean() {
Developer dev = developerService.getDeveloperById(5);
assertEquals("David", dev.getName());
}
}
Hoy en día, es preferible confiar en el enfoque de clase, ya que XML generalmente se considera un enfoque desactualizado para registrar beans. Si tiene más de una clase, por supuesto, simplemente las especificaría a través de classes = {TestBean.class, TestBean2.class, TestBean3.class}
, etc.
Esto nos lleva a la @Test
anotación, que se tratará en detalle a continuación. Por ahora, usémoslo simplemente con fines ilustrativos.
@WebAppConfiguration
Si desea asegurarse de que Spring cargue una WebApplicationContext
para sus pruebas en lugar de la normal ApplicationContext
, puede usar la @WebAppConfiguration
anotación junto con la @ContextConfiguration
anotación:
@ContextConfiguration(classes = TestBean.class)
@WebAppConfiguration
public class ApplicationTests {
@Autowired
private DeveloperService;
// Rest of the code...
}
Alternativamente, puede especificar la value
bandera, o más bien, la ubicación del WebApplicationContext
, si no se encuentra en el src/main/webapp
directorio predeterminado :
@WebAppConfiguration("some/other/location")
public class ApplicationTests {}
@ContextHierarchy
Otra anotación que generalmente se usa con poca frecuencia (personalmente no he visto a nadie usarla en un proyecto) es la @ContextHierarchy
anotación.
Permite al desarrollador definir múltiples @ContextConfiguration
s en niveles a través de una relación padre-hijo.
La idea es que los contextos secundarios puedan usar los beans registrados en los contextos principales y esto mejora la reutilización de los beans:
@ContextHierarchy({
@ContextConfiguration(classes = ApplicationTestConfiguration.class),
@ContextConfiguration(classes = WebApplicationTestConfiguration.class)
})
public class ApplicationTests {
}
Si desea leer más sobre esta anotación, la documentación contiene información detallada sobre la jerarquía de contexto.
@ActiveProfiles
La @ActiveProfiles
anotación es una anotación bastante sencilla y sencilla. Define qué perfil debe estar activo al cargar la configuración de contexto:
@ContextConfiguration
@ActiveProfiles("dev")
public class ApplicationTests {}
Esto indica que el perfil «dev» debe estar activo.
El nombre de la anotación implica que podemos definir múltiples perfiles, que podemos:
Te puede interesar:Trabajar con archivos zip en Java@ContextConfiguration
@ActiveProfiles({"dev", "prod"})
public class ApplicationTests {}
Si desea leer más sobre Spring Profiles, ¡lo tenemos cubierto!
@Rollback
A veces, cuando se trata de bases de datos, queremos revertir los cambios que hemos realizado, especialmente si hemos provocado una excepción.
La @Rollback
anotación define si la transacción de un método marcado con @Transactional
debe revertirse una vez que se haya completado la llamada al método de prueba.
Se puede aplicar a nivel de clase y método:
- Nivel de clase : define la reversión predeterminada para todos los métodos de prueba dentro de la clase.
- Nivel de método : define la reversión para el método de prueba específico
@Rollback(true)
@Test
public void someTest() {
// ...calling some transactional method
}
Una vez realizada la prueba, se revertirán todos los cambios realizados por el método transaccional.
Un punto interesante a destacar es el hecho de que puede establecer el indicador opcional en false
, en el que Spring garantiza que los cambios no se reviertan. Establecer la @Rollback
anotación en false
se comportará exactamente igual que @Commit
.
@Commit
Como anexo a la sección anterior, la @Commit
anotación se usa cuando queremos asegurar los cambios en la base de datos después de ejecutar los métodos de prueba.
Se comporta igual que @Rollback(false)
y se puede aplicar a nivel de clase o método:
@Commit
@Test
public void someTest() {
// ...calling some transactional method
}
@BeforeTransaction
A veces, queremos ejecutar piezas de código específicas antes de realizar las transacciones. Para hacerlo, obviamente necesitamos definir métodos escritos específicamente para esto.
Para invocarlos antes de cada transacción, simplemente los anotamos con la @BeforeTransaction
anotación:
@BeforeTransaction
void methodBeforeTransaction() {
// ...ran before a transaction
}
Para que la anotación funcione correctamente, debe marcar sus métodos transaccionales con @Transactional
.
Nota : A partir de Spring 4.3, no es necesario que estos métodos sean públicos.
@AfterTransaction
Con la misma naturaleza que la @BeforeTransaction
anotación, la @AfterTransaction
anotación ejecuta un método determinado después de que se ha realizado una transacción:
@AfterTransaction
void methodAfterTransaction() {
// ...ran after a transaction
}
Nota : A partir de Spring 4.3, no es necesario que estos métodos sean públicos.
Te puede interesar:Clasificación topológica en Java@Sql
Usando la @Sql
anotación y pasando el nombre (s) de los esquemas que deseamos que se ejecuten, podemos ejecutar mediante programación (o declarativamente) scripts SQL.
De forma predeterminada, estos scripts se ejecutan antes que cualquier @Before
método.
Si definimos un script, como createTable.sql
:
CREATE TABLE ITEM (ITEM_ID INT PRIMARY KEY, ITEM_NAME VARCHAR(256) NOT NULL);
Podemos referenciarlo y ejecutarlo fácilmente:
@Test
@Sql("/createTable.sql")
public void itemTest {
// ...some code that depends on the sql script above
}
@SqlGroup
La @SqlGroup
anotación nos permite agrupar varios scripts SQL y ejecutarlos.
Si tenemos otro script, como uno para eliminar la misma tabla dropTable.sql
,:
DROP TABLE ITEM;
Podemos agrupar el createTable.sql
script con el dropTable.sql
script para ejecutar antes y después del método de prueba, por ejemplo:
@Test
@SqlGroup({
@Sql(executionPhase = ExecutionPhase.BEFORE_TEST_METHOD, scripts = ""),
@Sql(executionPhase = ExecutionPhase.AFTER_TEST_METHOD, scripts = ""),
})
public void itemTest {
// ...item table gets created, tested by the code and then dropped
}
@SqlConfig
Como su nombre lo indica, siguiendo los ejemplos de anotaciones estándar de Spring, la @SqlConfig
anotación se usa para definir la configuración de los scripts SQL: cómo se analizan y ejecutan.
Se puede aplicar a nivel de clase o de método. Las pruebas de integración, que requieren una configuración global para todos los scripts SQL en ejecución, generalmente usan el enfoque a nivel de clase, mientras que el enfoque a nivel de método es para configuraciones locales de ciertos métodos:
@Test
@Sql(scripts = "/createTable.sql",
config = @SqlConfig(attribute = "val", attribute2 = "val"))
public void itemTest {
// Some code...
}
Hay 9 atributos que puede pasar a la @SqlConfig
anotación:
blockCommentEndDelimiter
: Delimitador final para comentarios de bloqueblockCommentStartDelimiter
: Delimitador de inicio para comentarios de bloquecommentPrefix
: El prefijo para comentarios de una sola líneadataSource
: Nombre deldataSource
frijolencoding
: Especificando la codificación de los scriptserrorMode
: Qué modo usar cuando se encuentra un errorseparator
: El carácter que se usa para separar declaracionestransactionManager
: Nombre del bean administrador de transaccionestransactionMode
: Qué modo usar al ejecutar scripts SQL
@SpringBootTest
La @SpringBootTest
anotación busca la clase de prueba anotada con la @SpringBootConfiguration
que en la mayoría de los casos es nuestra clase de aplicación principal, ya que @SpringBootApplication
incluye la anotación anterior dentro de sí misma.
Una vez encontrado, construye el contexto de la aplicación para el entorno de prueba. Incluso puede iniciar un entorno web utilizando el webEnvironment
atributo:
@SpringBootTest
public class IntegrationTests {
// Rest of the code
}
@SpringBootTest(webEnvironment = pringBootTest.WebEnvironment.RANDOM_PORT)
public class WebEnvIntegrationTests {
// Rest of the code
}
@DataJpaTest
Usando la @DataJpaTest
anotación, podemos probar aplicaciones JPA. Se aplica a nivel de clase y construye un contexto de aplicación para todas las @Enitity
clases, junto con una base de datos incorporada que se aplica de forma predeterminada.
Nota : Las @Component
clases regulares no se cargan en el contexto de la aplicación creado por la @DataJpaTest
anotación.
Se utiliza junto con la @RunWith(SpringRunner.class)
anotación, que indica qué instalaciones utilizará la clase marcada.
De forma predeterminada, todas las transacciones JPA se revertirán (puede cambiar este comportamiento aplicando @Rollback(false)
o @Commit
):
@RunWith(SpringRunner.class)
@DataJpaTest
public class SomeJpaTest {
// Rest of the code
}
Sin embargo, esta es una prueba clásica de JPA, si desea utilizar la base de datos real, en lugar de la base de datos incorporada en la memoria proporcionada, simplemente puede agregar otra anotación para evitar tal comportamiento:
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureTestDatabase(replace = Replace.NONE)
public class SomeJpaTest {
// Rest of the code
}
@DataMongoTest
Muy similar a la @DataJpaTest
anotación, para realizar pruebas clásicas de MongoDB, aplicamos la @DataMongoTest
anotación junto con la @RunWith(SpringRunner.class)
anotación.
Tenga en cuenta que esta anotación se usa cuando la prueba se aplica solo para probar componentes de MongoDB y agrega solo @Document
clases al contexto de la aplicación:
@RunWith(SpringRunner.class)
@DataMongoTest
public class SomeMongoTest {
// Rest of the code
}
Por otra parte, si desea ejecutar esto con la base de datos real, y no con la base de datos incrustada en memoria proporcionada por Mongo, puede excluir esta opción:
@RunWith(SpringRunner.class)
@DataMongoTest(excludeAutoConfiguration = EmbeddedMongoAutoConfiguration.class)
public class SomeMongoTest {
// Rest of the code
}
@WebMvcTest
Una vez más, muy similar a la @DataJpaTest
y las @DataMongoTest
anotaciones, para llevar a cabo pruebas clásicas Spring MVC, aplicamos la @WebMvcTest
anotación junto a la @RunWith(SpringRunner.class)
anotación.
Tenga en cuenta que los efectos de esta anotación solo se aplican a la infraestructura MVC. Dicho esto, no crea una instancia de todo el contexto.
La anotación se puede usar para probar un solo controlador, pasándolo como un atributo como @WebMvcTest(SomeController.class)
.
Para crear una instancia de otras dependencias necesarias, como los servicios, normalmente usamos la @MockBean
anotación. @WebMvcTest
Configura MockMvc
que se puede usar para probar fácil y rápidamente los controladores MVC y crear instancias de otros colaboradores:
@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class ControllerTests {
// Auto-configured to make mocking easier
@Autowired
private MockMvc mockMvc;
@MockBean
private SomeBean someBean;
@Test
public void someTest() {
// Test logic
}
}
@MockBean
Al probar unidades específicas, como por ejemplo, un controlador, queremos aislarlas tanto como podamos. Dado que la mayoría de los componentes de la aplicación Spring dependen de muchos otros componentes (dependencias), es esencial asegurarse de que todos estos componentes se puedan probar individualmente.
Para aislar con éxito los objetos que queremos probar, sin dejar de permitir que la aplicación funcione bien, simulamos o simulamos las dependencias. Se @MockBean
usa una anotación cuando queremos simular una dependencia en una aplicación:
@RunWith(SpringRunner.class)
@WebMvcTest(HomeController.class)
public class ControllerTests {
// Auto-configured to make mocking easier
@Autowired
private MockMvc mockMvc;
@MockBean
private SomeBean someBean;
@Test
public void someTest() {
// Test logic
}
}
En este ejemplo, la someBean
dependencia simula una dependencia real. Si el bean existe en el contexto, el simulacro lo reemplaza. Si no existe, el simulacro se agrega al contexto como un bean.
Nota : hay una diferencia entre las anotaciones @Mock
y @MockBean
. La @Mock
anotación proviene de la biblioteca Mockito y es equivalente a llamar al Mockito.mock()
método. Por otro lado, @MockBean
es el contenedor de la biblioteca Spring de la @Mock
anotación.
@AutoConfigureMockMvc
Como sugiere el nombre, la @AutoConfigureMockMvc
anotación, cuando se aplica a una clase de prueba, se configurará automáticamente MockMvc
, de la misma manera que @WebMvcTest
la configurará automáticamente.
@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ControllerTests {
@Autowired
private MockMvc mockMvc;
// Rest of the logic
}
Si desea enfocarse solo en la capa web, considere usar la @WebMvcTest
anotación en su lugar.
@JsonTest
Muchas aplicaciones se ocupan de la serialización / deserialización de JSON. Por lo tanto, tiene mucho sentido asegurarse de que funcione correctamente mientras se prueba la aplicación. Al usar la @JsonTest
anotación, Spring configura automáticamente el mapeador JSON compatible (Jackson, Gson o Jsonb).
Por lo general, se usa junto con @RunWith(SpringRunner.class)
y se usa para pruebas JSON clásicas, buscando @JsonComponent
s.
@RunWith(SpringRunner.class)
@JsonTest
public class JsonTests {
@Test
public void someJsonTest() {
// Rest of the logic
}
}
@TestPropertySource
La @TestPropertySource
anotación se aplica a nivel de clase y define las ubicaciones de las fuentes de propiedad que queremos usar para la prueba.
Estas propiedades se guardan como un conjunto de @PropertySource
s en el entorno del contexto de la aplicación. Estas propiedades tienen prioridad sobre las propiedades del sistema o de la aplicación.
Esencialmente, cuando deseamos anular las propiedades del sistema / aplicación con propiedades específicas para nuestras pruebas, simplemente anotamos la clase de prueba:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
@TestPropertySource("classpath:applicationtest.properties")
public class ApplicationTest {
// Rest of the logic
}
Por otro lado, puede especificar propiedades en línea, en lugar de todo el archivo de propiedades:
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestConfiguration.class)
@TestPropertySource(properties = {"sa.website_name = Pharos.sh", "sa.website_url = www.Pharos.sh.com"})
public class ApplicationTest {
// Rest of the logic
}
@Timed
La @Timed
anotación define el tiempo en milisegundos en el que el método de prueba debe finalizar la ejecución; de lo contrario, fallará:
@Timed(millis = 1000)
public void testMethod() {
// Some test logic
}
Si la prueba tarda más de un segundo en ejecutarse, fallará. Esto incluye todas las repeticiones del método, si la @Repeat
anotación está presente.
@Repeat
La @Repeat
anotación define cuántas veces se debe repetir un método de prueba:
@Repeat(5)
@Test
public void testMethod() {
// Some test logic
}
Esta prueba se repetirá cinco veces.
Conclusión
El marco Spring es un marco poderoso y robusto que realmente cambió el juego cuando se trata de desarrollar aplicaciones web. Entre todas las cosas que admite, ofrece un excelente soporte TDD para Spring Applications y permite a los desarrolladores configurar fácil y rápidamente cualquier tipo de pruebas.
.
Te puede interesar:Web Scraping a la manera de Java