SpringBoot: Testing con Spring Test
Aprende a realizar testing efectivo en Spring Boot con Spring Test. Domina pruebas unitarias, integración, mocking y TestContainers.
Aprende SpringBoot GRATIS y certifícateTesting con Spring Test
El testing es una práctica fundamental en el desarrollo de aplicaciones Spring Boot que garantiza la calidad y confiabilidad del código. Spring Framework proporciona un conjunto completo de herramientas de testing a través de Spring Test, que se integra perfectamente con el ecosistema de Spring Boot para facilitar la creación de pruebas efectivas.
Fundamentos del testing en Spring Boot
Spring Boot incluye por defecto el starter de testing que proporciona todas las dependencias necesarias para escribir pruebas. Este starter incluye JUnit 5, Mockito, AssertJ y las utilidades específicas de Spring Test, creando un entorno completo para diferentes tipos de pruebas.
La arquitectura de testing en Spring Boot se basa en el concepto de contexto de aplicación. Spring Test puede cargar un contexto completo o parcial de la aplicación, permitiendo probar componentes de forma aislada o en conjunto según las necesidades específicas de cada prueba.
@SpringBootTest
class ApplicationTests {
@Test
void contextLoads() {
// Esta prueba verifica que el contexto de Spring se carga correctamente
}
}
Tipos de pruebas en Spring Boot
Spring Boot facilita la implementación de diferentes niveles de testing mediante anotaciones especializadas. Cada tipo de prueba está diseñado para verificar aspectos específicos de la aplicación con el nivel de integración apropiado.
Pruebas unitarias
Las pruebas unitarias se centran en probar componentes individuales de forma aislada. Spring Test proporciona utilidades para crear mocks y configurar el contexto mínimo necesario.
@ExtendWith(MockitoExtension.class)
class UserServiceTest {
@Mock
private UserRepository userRepository;
@InjectMocks
private UserService userService;
@Test
void shouldCreateUser() {
// Arrange
User user = new User("Juan", "juan@email.com");
when(userRepository.save(any(User.class))).thenReturn(user);
// Act
User result = userService.createUser("Juan", "juan@email.com");
// Assert
assertThat(result.getName()).isEqualTo("Juan");
assertThat(result.getEmail()).isEqualTo("juan@email.com");
}
}
Pruebas de integración
Las pruebas de integración verifican la interacción entre múltiples componentes. Spring Boot proporciona anotaciones específicas para cargar partes del contexto de aplicación según el tipo de integración que se desea probar.
@DataJpaTest
class UserRepositoryTest {
@Autowired
private TestEntityManager entityManager;
@Autowired
private UserRepository userRepository;
@Test
void shouldFindUserByEmail() {
// Arrange
User user = new User("Ana", "ana@email.com");
entityManager.persistAndFlush(user);
// Act
Optional<User> found = userRepository.findByEmail("ana@email.com");
// Assert
assertThat(found).isPresent();
assertThat(found.get().getName()).isEqualTo("Ana");
}
}
Anotaciones principales de Spring Test
Spring Test proporciona un conjunto de anotaciones especializadas que simplifican la configuración de diferentes tipos de pruebas. Cada anotación carga únicamente los componentes necesarios, optimizando el tiempo de ejecución de las pruebas.
@SpringBootTest carga el contexto completo de la aplicación, ideal para pruebas de integración end-to-end:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class IntegrationTest {
@Autowired
private TestRestTemplate restTemplate;
@Test
void shouldReturnUserList() {
ResponseEntity<String> response = restTemplate.getForEntity("/api/users", String.class);
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
}
}
@WebMvcTest se enfoca en la capa web, cargando únicamente los controladores y componentes relacionados:
@WebMvcTest(UserController.class)
class UserControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private UserService userService;
@Test
void shouldReturnUser() throws Exception {
User user = new User("Carlos", "carlos@email.com");
when(userService.findById(1L)).thenReturn(user);
mockMvc.perform(get("/api/users/1"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name").value("Carlos"));
}
}
@DataJpaTest configura únicamente la capa de persistencia, proporcionando una base de datos en memoria para las pruebas:
@DataJpaTest
class ProductRepositoryTest {
@Autowired
private ProductRepository productRepository;
@Test
void shouldSaveAndRetrieveProduct() {
Product product = new Product("Laptop", 999.99);
Product saved = productRepository.save(product);
assertThat(saved.getId()).isNotNull();
assertThat(saved.getName()).isEqualTo("Laptop");
}
}
Configuración del entorno de testing
Spring Boot permite personalizar el entorno de testing mediante perfiles específicos y archivos de configuración dedicados. Esta flexibilidad facilita la creación de entornos de prueba que replican condiciones reales sin afectar los datos de producción.
El archivo application-test.properties
permite definir configuraciones específicas para las pruebas:
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.hibernate.ddl-auto=create-drop
logging.level.org.springframework.web=DEBUG
La anotación @ActiveProfiles activa perfiles específicos durante la ejecución de las pruebas:
@SpringBootTest
@ActiveProfiles("test")
class ServiceIntegrationTest {
@Autowired
private EmailService emailService;
@Test
void shouldSendEmailInTestMode() {
// El servicio usará la configuración del perfil 'test'
boolean sent = emailService.sendWelcomeEmail("test@email.com");
assertThat(sent).isTrue();
}
}
Mocking y stubbing
El mocking es una técnica esencial en las pruebas que permite simular el comportamiento de dependencias externas. Spring Test se integra con Mockito para proporcionar capacidades avanzadas de mocking directamente en el contexto de Spring.
@MockBean reemplaza beans del contexto de Spring con mocks, permitiendo controlar su comportamiento durante las pruebas:
@SpringBootTest
class OrderServiceTest {
@MockBean
private PaymentService paymentService;
@MockBean
private InventoryService inventoryService;
@Autowired
private OrderService orderService;
@Test
void shouldProcessOrderSuccessfully() {
// Arrange
when(inventoryService.isAvailable("PRODUCT_123")).thenReturn(true);
when(paymentService.processPayment(100.0)).thenReturn(true);
// Act
Order result = orderService.createOrder("PRODUCT_123", 100.0);
// Assert
assertThat(result.getStatus()).isEqualTo(OrderStatus.CONFIRMED);
verify(paymentService).processPayment(100.0);
verify(inventoryService).reserveProduct("PRODUCT_123");
}
}
TestContainers para pruebas realistas
TestContainers permite ejecutar pruebas con bases de datos reales en contenedores Docker, proporcionando un entorno de testing más cercano a producción. Spring Boot 3.1+ incluye soporte nativo para TestContainers.
@SpringBootTest
@Testcontainers
class DatabaseIntegrationTest {
@Container
static PostgreSQLContainer<?> postgres = new PostgreSQLContainer<>("postgres:15")
.withDatabaseName("testdb")
.withUsername("test")
.withPassword("test");
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", postgres::getJdbcUrl);
registry.add("spring.datasource.username", postgres::getUsername);
registry.add("spring.datasource.password", postgres::getPassword);
}
@Autowired
private UserRepository userRepository;
@Test
void shouldPersistUserInRealDatabase() {
User user = new User("Maria", "maria@email.com");
User saved = userRepository.save(user);
assertThat(saved.getId()).isNotNull();
assertThat(userRepository.count()).isEqualTo(1);
}
}
Lecciones de este módulo de SpringBoot
Lecciones de programación del módulo Testing con Spring Test del curso de SpringBoot.
Ejercicios de programación en este módulo de SpringBoot
Evalúa tus conocimientos en Testing con Spring Test con ejercicios de programación Testing con Spring Test de tipo Test, Puzzle, Código y Proyecto con VSCode.