Imaginemos que estamos creando un microservicio responsable de procesar pedidos en una tienda online. Procesa solicitudes HTTP, llama a servicios para verificar la disponibilidad de productos en el almacén, interactúa con la base de datos para guardar la información de los pedidos. Todo esto es un conjunto de componentes que interactúan. Y aunque los hayas probado por separado con unit tests, eso no garantiza que todo funcione junto como debe. Ahí es donde entran las pruebas de integración.
Las pruebas de integración a nivel de microservicio permiten:
- Comprobar la interacción entre controllers, services, repositories y otros componentes.
- Asegurarse de que todo el microservicio funciona correctamente sin depender de dependencias externas reales.
- Emular solicitudes HTTP reales y verificar cómo la aplicación las procesa y devuelve respuestas.
MockMvc: herramienta clave para las pruebas de integración
Antes de meternos con las pruebas, vamos a ver qué es MockMvc.
MockMvc es una herramienta cómoda de Spring Test que permite:
- Modelar solicitudes HTTP a tu aplicación sin arrancar un servidor web real.
- Verificar cómo tu controller procesa las solicitudes, devuelve respuestas y trabaja con servicios internos.
- Simular escenarios reales del API, incluyendo envío de parámetros, cuerpo de la solicitud, configuración de headers y mucho más.
Piénsalo así: en vez de montar todo el coche y hacerlo rodar en una pista de pruebas, pruebas solo el motor, pero bajo una carga cercana a la real. En pocas palabras: MockMvc permite testear la capa web de la aplicación de forma aislada, sin necesidad de levantar todo el servidor.
¿Por qué MockMvc es mejor para pruebas de integración?
MockMvc ofrece una forma ligera de probar:
- Más rápido que arrancar pruebas de integración completas con servidor levantado. Ahorra tiempo, especialmente en proyectos grandes.
- Aísla la capa que estás probando. Si la base de datos u otros sistemas externos no están listos, no detendrán las pruebas, porque puedes mockearlos.
- API flexible. MockMvc facilita el envío de solicitudes y la verificación de cómo tus controllers las manejan.
Preparación para trabajar con MockMvc
Antes de que nos sumerjamos en ejemplos, asegúrate de que tu proyecto está configurado para testing.
Para empezar, confirma que en tu pom.xml (o build.gradle) están añadidas las dependencias de test:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Para trabajar con MockMvc necesitarás la siguiente configuración en la clase de test:
@SpringBootTest // Sube el contexto de Spring para las pruebas
@AutoConfigureMockMvc // Habilita la configuración automática de MockMvc
Fácil, ¿no? Ahora tu clase de tests está lista para trabajar.
Práctica: Probar un REST API usando MockMvc
Basta de teoría, ¡es hora de ver cómo funciona todo en la práctica!
Supongamos que tenemos un microservicio para gestionar libros, con un REST API para trabajar con la colección de libros.
Controller para probar
Aquí hay un ejemplo de controller que expone métodos HTTP para trabajar con libros:
@RestController
@RequestMapping("/books")
public class BookController {
private final BookService bookService;
public BookController(BookService bookService) {
this.bookService = bookService;
}
@GetMapping("/{id}")
public ResponseEntity<Book> getBook(@PathVariable Long id) {
return ResponseEntity.ok(bookService.findBookById(id));
}
@PostMapping
public ResponseEntity<Book> createBook(@RequestBody Book book) {
return ResponseEntity.status(HttpStatus.CREATED).body(bookService.saveBook(book));
}
}
Tenemos dos métodos:
GET /books/{id}— devuelve un libro por su identificador.POST /books— añade un libro nuevo.
Escribir tests para el controller con MockMvc
Ahora escribamos tests para este controller. Para empezar, crea la clase de tests:
@SpringBootTest
@AutoConfigureMockMvc
class BookControllerTest {
@Autowired
private MockMvc mockMvc;
@MockBean
private BookService bookService; // Mockeamos la dependencia del servicio
@Test
void testGetBook() throws Exception {
// Datos para la prueba
Book book = new Book(1L, "The Hobbit", "J.R.R. Tolkien");
Mockito.when(bookService.findBookById(1L)).thenReturn(book);
// Enviamos una solicitud GET y verificamos el resultado
mockMvc.perform(get("/books/1"))
.andExpect(status().isOk()) // Esperamos el estado 200 OK
.andExpect(jsonPath("$.title").value("The Hobbit")) // Verificamos el campo title
.andExpect(jsonPath("$.author").value("J.R.R. Tolkien")); // Verificamos el campo author
}
@Test
void testCreateBook() throws Exception {
// Datos para la prueba
Book book = new Book(null, "1984", "George Orwell");
Book savedBook = new Book(2L, "1984", "George Orwell");
Mockito.when(bookService.saveBook(Mockito.any())).thenReturn(savedBook);
// Enviamos una solicitud POST con datos JSON
String bookJson = """
{
"title": "1984",
"author": "George Orwell"
}
""";
mockMvc.perform(post("/books")
.contentType(MediaType.APPLICATION_JSON)
.content(bookJson))
.andExpect(status().isCreated()) // Esperamos el estado 201 Created
.andExpect(jsonPath("$.id").value(2L)) // Verificamos que el ID del libro = 2
.andExpect(jsonPath("$.title").value("1984")) // Verificamos el título
.andExpect(jsonPath("$.author").value("George Orwell")); // Verificamos el autor
}
}
¿Qué está pasando aquí?
- Anotaciones:
@SpringBootTestlevanta todo el contexto de Spring.@AutoConfigureMockMvcconfigura MockMvc automáticamente.@MockBeancrea un mock para la dependenciaBookService, que usaremos para aislar el test.
- Tests:
- En
testGetBookmockeamos el métodofindBookByIddel servicio para que devuelva un objetoBook. Luego enviamos una solicitud GET y comprobamos que la respuesta contiene los datos correctos. - En
testCreateBookmockeamos el métodosaveBook, enviamos una solicitud POST con JSON y verificamos que la respuesta contiene los datos del libro creado.
- En
- MockMvc API:
mockMvc.perform(...)ejecuta una solicitud HTTP.andExpect(...)incluye todas las aserciones del resultado, desde el status hasta el contenido JSON.
Errores comunes al usar MockMvc
Pues bien, a qué conviene prestar atención:
- No declarar la dependencia de
MockMvco no usar@AutoConfigureMockMvc. En ese caso los tests no podrán usar MockMvc. - Errores de serialización JSON. Revisa si Jackson está incluido en tu proyecto.
- Falta de mocks para las dependencias. MockMvc prueba solo el controller, así que asegúrate de mockear los services con
@MockBean.
MockMvc es una herramienta increíblemente potente para testear la interacción con tus controllers. Permite probar solicitudes HTTP al vuelo y detectar al instante errores que podrían aparecer solo en uso real. Con ella puedes estar tranquilo sobre el correcto funcionamiento de tu API antes del deploy a producción.
GO TO FULL VERSION