CodeGym /Cursos /Módulo 5. Spring /Lección 139: Práctica: pruebas de controladores con MockM...

Lección 139: Práctica: pruebas de controladores con MockMvc

Módulo 5. Spring
Nivel 9 , Lección 8
Disponible

Si alguna vez has querido ver cómo tu API vive su mejor vida, pero no quieres arrancar todo el servidor y andar con Postman, — MockMvc viene al rescate. Hoy nos meteremos de lleno en el uso práctico de MockMvc para testear controladores en tu aplicación Spring.

MockMvc — es una herramienta para probar Spring MVC. Te permite ejecutar peticiones HTTP a tus controladores sin necesidad de levantar un servidor real. En otras palabras, MockMvc es tu Postman de bolsillo, pero mucho más integrado y orientado a la automatización. Con MockMvc puedes simular solicitudes con facilidad, comprobar las respuestas de los controladores, probar escenarios de error y capturar los estados HTTP.


Preparación del entorno

Antes de ponerte a testear con MockMvc, asegúrate de que tu aplicación está configurada para trabajar con tests. Para eso, en el fichero de build de tu proyecto (por ejemplo, pom.xml, si usas Maven) deben añadirse las dependencias:


<dependencies>
    <!-- Dependencia para Spring Boot Test -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

Ejemplo de controlador

Para probar vamos a usar un REST-controller que maneja la entidad User. Así podría lucir:


@RestController
@RequestMapping("/api/users")
public class UserController {

    @GetMapping("/{id}")
    public ResponseEntity<User> getUserById(@PathVariable("id") Long id) {
        // Por ejemplo, aquí se llama a un servicio que devuelve el usuario
        User user = new User(id, "John Doe");
        return ResponseEntity.ok(user);
    }

    @PostMapping
    public ResponseEntity<User> createUser(@RequestBody User user) {
        // Simulación de creación de usuario
        return ResponseEntity.status(HttpStatus.CREATED).body(user);
    }

    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable("id") Long id) {
        // Imaginemos que el usuario se ha borrado correctamente
        return ResponseEntity.noContent().build();
    }
}

Práctica: probando el controlador con MockMvc

Ahora nos ponemos con las pruebas de UserController. Vamos a testear los métodos básicos: obtener, crear y borrar un usuario.

Configuración de MockMvc en los tests

En Spring Boot puedes usar la anotación @WebMvcTest para levantar el contexto solo para los componentes web, como los controladores.


@WebMvcTest(UserController.class) // Levantamos el contexto solo para UserController
class UserControllerTest {

    @Autowired
    private MockMvc mockMvc; // MockMvc permite enviar peticiones.

    @Test
    void testGetUserById() throws Exception {
        // La lógica del test irá aquí
    }
}

Prueba del GET

Empezamos por lo básico: comprobamos que el controlador responde correctamente a la petición de obtención de un usuario.


@Test
void testGetUserById() throws Exception {
    mockMvc.perform(get("/api/users/{id}", 1)) // Enviamos una petición GET al endpoint.
            .andExpect(status().isOk()) // Comprobamos que el estado de la respuesta es 200 OK.
            .andExpect(content().contentType(MediaType.APPLICATION_JSON)) // Comprobamos el tipo de contenido.
            .andExpect(jsonPath("$.id").value(1)) // Comprobamos que el campo "id" es 1.
            .andExpect(jsonPath("$.name").value("John Doe")); // Comprobamos que el campo "name" es "John Doe".
}

Aquí usamos jsonPath para verificar el contenido del JSON de la respuesta. Es superútil y permite trabajar incluso con objetos anidados.

Prueba del POST

Ahora añadimos la prueba para el método de creación de usuario.


@Test
void testGetUserById() throws Exception {
    mockMvc.perform(get("/api/users/{id}", 1)) // Enviamos una petición GET al endpoint.
            .andExpect(status().isOk()) // Comprobamos que el estado de la respuesta es 200 OK.
            .andExpect(content().contentType(MediaType.APPLICATION_JSON)) // Comprobamos el tipo de contenido.
            .andExpect(jsonPath("$.id").value(1)) // Comprobamos que el campo "id" es 1.
            .andExpect(jsonPath("$.name").value("John Doe")); // Comprobamos que el campo "name" es "John Doe".
}

Aquí ves lo fácil que es enviar el cuerpo de la petición indicando datos JSON. También verificamos la presencia de la cabecera Location, que a menudo se usa en respuestas a peticiones POST.

Prueba del DELETE

Probamos la eliminación de un usuario. Aquí es importante asegurarse de que el controlador devuelve el estado 204 No Content.


@Test
void testDeleteUser() throws Exception {
    mockMvc.perform(delete("/api/users/{id}", 1)) // Enviamos una petición DELETE.
            .andExpect(status().isNoContent()); // Comprobamos que el estado de la respuesta es 204 No Content.
}

Pruebas de escenarios negativos

No siempre tus endpoints responden con éxito. A veces lanzan errores, y esos escenarios también es importante testear.

Supongamos que el método getUserById puede lanzar una excepción si el usuario no existe:


@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable("id") Long id) {
    if (id < 0) {
        throw new UserNotFoundException("User not found");
    }
    User user = new User(id, "John Doe");
    return ResponseEntity.ok(user);
}

Aquí tienes un ejemplo de test para ese escenario:


@Test
void testGetUserNotFound() throws Exception {
    mockMvc.perform(get("/api/users/{id}", -1)) // Petición con ID incorrecto.
            .andExpect(status().isNotFound()) // Esperamos el estado 404 Not Found.
            .andExpect(jsonPath("$.error").value("User not found")); // Comprobamos el mensaje de error.
}

Errores típicos y cómo solucionarlos

Muchos principiantes se encuentran con problemas al usar MockMvc. Por ejemplo, se olvidan de poner @WebMvcTest, y entonces el test empieza a traer dependencias de toda la base de datos, servicios y otros componentes de la aplicación. No olvides configurar MockMvc y aislar las capas que estás probando.

Otro error común — la ausencia de parámetros en las peticiones. Por ejemplo, si olvidas pasar el cuerpo de la petición en un POST, MockMvc devolverá un error 400. Revisa siempre qué necesita tu endpoint.


¿Qué sigue?

Probar con MockMvc es solo una etapa en la cadena de aseguramiento de calidad. En proyectos reales combinarás Unit, pruebas de integración y pruebas funcionales para minimizar bugs y dormir más tranquilo. Más adelante en el curso profundizaremos en pruebas de integración con MockMvc y en conectar bases de datos reales usando Testcontainers.

Para un estudio más detallado, puedes consultar la documentación oficial de MockMvc.

Comentarios
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION