CodeGym /Cursos /Módulo 5. Spring /Lección 265: Práctica: pruebas de REST API usando MockMvc...

Lección 265: Práctica: pruebas de REST API usando MockMvc

Módulo 5. Spring
Nivel 21 , Lección 4
Disponible

Cuando desarrollamos una aplicación web con Spring — necesitamos comprobar que funciona correctamente. Para eso existe la estupenda herramienta MockMvc. Imagina que tu aplicación es una cafetería moderna. En la situación normal, para probar cómo funciona tendrías que poner en marcha todo el local: la cocina, la sala, sentar a los camareros. Es como arrancar un servidor completo — lento y tedioso. MockMvc es como si crearas una miniatura del café con un solo cocinero y una ventanilla de salida. Por esa ventanilla puedes hacer pedidos (enviar requests) y recibir platos listos (responses), sin tener que levantar todo el local. En el mundo de Spring esto significa que podemos testear la aplicación en un modo ligero — sin servidor completo ni conexión a la base de datos.


Preparación del entorno para las pruebas

Para empezar, comprobemos que hemos añadido todas las dependencias necesarias para las pruebas. En tu pom.xml (si usas Maven) o build.gradle (si usas Gradle) deberían estar las dependencias para Spring Boot Starter Test:

Maven:


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

Gradle:


testImplementation 'org.springframework.boot:spring-boot-starter-test'

MockMvc ya está incluido en Spring Boot Starter Test, así que no hacen falta dependencias adicionales.


Prueba sencilla de REST API con MockMvc

Datos de entrada

Supongamos que tenemos un REST-controller para manejar entidades "Product":


@RestController
@RequestMapping("/api/products")
public class ProductController {

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        // Esto es un stub simplificado. En la vida real aquí habría una llamada al servicio.
        if (id == 1L) {
            return ResponseEntity.ok(new Product(1L, "Café", 5.0));
        }
        return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
    }
}

Y tenemos la entidad Product:


public class Product {
    private Long id;
    private String name;
    private Double price;

    // Constructores, getters y setters.
    public Product(Long id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    // Getters y setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}

Escribiendo los tests

Ahora vamos a escribir tests para ProductController. Queremos asegurarnos de que:

  1. Si pedimos el recurso con un ID existente, recibimos el resultado correcto.
  2. Si el recurso con el ID indicado no existe, se devuelve el status 404.

public class Product {
    private Long id;
    private String name;
    private Double price;

    // Constructores, getters y setters.
    public Product(Long id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    // Getters y setters
    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Double getPrice() {
        return price;
    }

    public void setPrice(Double price) {
        this.price = price;
    }
}
  1. La anotación @WebMvcTest: indica que vamos a testear solo la capa de controllers. Spring levantará automáticamente el entorno mínimo necesario.
  2. El método mockMvc.perform(): emula una petición HTTP. Aquí indicamos la ruta (/api/products/1) y el método (GET).
  3. Los métodos andExpect(): nos ayudan a verificar que la aplicación devuelve la respuesta esperada. Podemos comprobar:
    • El status de la respuesta (isOk(), isNotFound() y otros).
    • El tipo de contenido (contentType()).
    • El contenido del JSON-response (jsonPath()).

Probando solicitudes POST

Ahora añadimos en nuestro controller un método para crear un producto:

@PostMapping
public ResponseEntity<Product> createProduct(@RequestBody Product product) {
    product.setId(2L); // Stub: siempre devolvemos el mismo ID
    return ResponseEntity.status(HttpStatus.CREATED).body(product);
}

Escribamos un test para este método. Queremos asegurarnos de que:

  1. Una POST con datos correctos crea el producto y devuelve el status 201 (Created).
  2. En el cuerpo de la respuesta se devuelve el producto creado.

@Test
public void testCreateProduct() throws Exception {
    String newProductJson = """
        {
            "name": "Té",
            "price": 3.5
        }
    """;

    mockMvc.perform(post("/api/products") // Emulamos una petición POST
            .contentType(MediaType.APPLICATION_JSON) // Indicamos que el body es JSON
            .content(newProductJson)) // Pasamos los datos JSON
            .andExpect(status().isCreated()) // Esperamos status 201 Created
            .andExpect(content().contentType(MediaType.APPLICATION_JSON)) // La respuesta también JSON
            .andExpect(jsonPath("$.id").value(2)) // Comprobamos el ID
            .andExpect(jsonPath("$.name").value("Té")) // Comprobamos el nombre del producto
            .andExpect(jsonPath("$.price").value(3.5)); // Comprobamos el precio del producto
}

Errores comunes y particularidades

  1. Error "No qualifying bean of type '...' found"
    Al usar @WebMvcTest en el entorno de test solo se levantan los controllers. Si tu controller tiene dependencias de servicios u otros componentes, no olvides mockearlos con Mockito:
    @MockBean
    private ProductService productService;
    
  2. Uso incorrecto de @Autowired
    Usa siempre las anotaciones correctas (@Autowired o @MockBean) para las dependencias.
  3. Formato JSON en las solicitudes
    Asegúrate de que los datos JSON que envías en los tests son válidos. Usa contentType(MediaType.APPLICATION_JSON).
  4. Problemas con jsonPath
    Se recomienda usar validadores online de JSONPath para comprobar que tu path está indicado correctamente.

En este punto hemos aprendido a testear REST API usando MockMvc. Estos conocimientos te ayudarán no solo a detectar bugs en etapas tempranas del desarrollo, sino también a afrontar entrevistas donde te pueden pedir que demuestres trabajo con MockMvc.

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