Anotaciones de Spring: Pruebas

A

Introducció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 starterdependencia 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 @BootstrapWithanotació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 ContextLoadero implementar TestContexts 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 @ContextConfigurationanotació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 @Configurationanotaciones así como cualquier clase que contiene @Beans.

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 asserts 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 @Testanotació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 WebApplicationContextpara sus pruebas en lugar de la normal ApplicationContext, puede usar la @WebAppConfigurationanotación junto con la @ContextConfigurationanotación:

@ContextConfiguration(classes = TestBean.class)
@WebAppConfiguration
public class ApplicationTests {

    @Autowired
    private DeveloperService;

    // Rest of the code...
}

Alternativamente, puede especificar la valuebandera, o más bien, la ubicación del WebApplicationContext, si no se encuentra en el src/main/webappdirectorio 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 @ContextHierarchyanotación.

Permite al desarrollador definir múltiples @ContextConfigurations 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 @ActiveProfilesanotació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:

@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 @Rollbackanotación define si la transacción de un método marcado con @Transactionaldebe 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 @Rollbackanotación en falsese comportará exactamente igual que @Commit.

@Commit

Como anexo a la sección anterior, la @Commitanotació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 @BeforeTransactionanotació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 @BeforeTransactionanotación, la @AfterTransactionanotació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.

@Sql

Usando la @Sqlanotació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 @Beforemé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 @SqlGroupanotació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.sqlscript con el dropTable.sqlscript 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 @SqlConfiganotació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 @SqlConfiganotación:

  • blockCommentEndDelimiter: Delimitador final para comentarios de bloque
  • blockCommentStartDelimiter: Delimitador de inicio para comentarios de bloque
  • commentPrefix: El prefijo para comentarios de una sola línea
  • dataSource: Nombre del dataSourcefrijol
  • encoding: Especificando la codificación de los scripts
  • errorMode: Qué modo usar cuando se encuentra un error
  • separator: El carácter que se usa para separar declaraciones
  • transactionManager: Nombre del bean administrador de transacciones
  • transactionMode: Qué modo usar al ejecutar scripts SQL

@SpringBootTest

La @SpringBootTestanotación busca la clase de prueba anotada con la @SpringBootConfigurationque en la mayoría de los casos es nuestra clase de aplicación principal, ya que @SpringBootApplicationincluye 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 webEnvironmentatributo:

@SpringBootTest
public class IntegrationTests {
    // Rest of the code
}

@SpringBootTest(webEnvironment = pringBootTest.WebEnvironment.RANDOM_PORT)
public class WebEnvIntegrationTests {
    // Rest of the code
}

@DataJpaTest

Usando la @DataJpaTestanotación, podemos probar aplicaciones JPA. Se aplica a nivel de clase y construye un contexto de aplicación para todas las @Enitityclases, junto con una base de datos incorporada que se aplica de forma predeterminada.

Nota : Las @Componentclases regulares no se cargan en el contexto de la aplicación creado por la @DataJpaTestanotació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 @DataJpaTestanotación, para realizar pruebas clásicas de MongoDB, aplicamos la @DataMongoTestanotació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 @Documentclases 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 @DataJpaTesty las @DataMongoTestanotaciones, para llevar a cabo pruebas clásicas Spring MVC, aplicamos la @WebMvcTestanotació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 @MockBeananotación. @WebMvcTestConfigura MockMvcque 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 @MockBeanusa 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 someBeandependencia 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 @Mocky @MockBean. La @Mockanotación proviene de la biblioteca Mockito y es equivalente a llamar al Mockito.mock()método. Por otro lado, @MockBeanes el contenedor de la biblioteca Spring de la @Mockanotación.

@AutoConfigureMockMvc

Como sugiere el nombre, la @AutoConfigureMockMvcanotación, cuando se aplica a una clase de prueba, se configurará automáticamente MockMvc, de la misma manera que @WebMvcTestla 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 @WebMvcTestanotació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 @JsonTestanotació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 @JsonComponents.

@RunWith(SpringRunner.class)
@JsonTest
public class JsonTests {
    @Test
    public void someJsonTest() {
        // Rest of the logic
    }
}

@TestPropertySource

La @TestPropertySourceanotació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 @PropertySources 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 @Timedanotació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 @Repeatanotación está presente.

@Repeat

La @Repeatanotació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.

.

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias para su correcto funcionamiento. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad