JavaRush /Курси /Модуль 5. Spring /Лекція 265: Практика: тестування REST API з використанням...

Лекція 265: Практика: тестування REST API з використанням MockMvc

Модуль 5. Spring
Рівень 21 , Лекція 4
Відкрита

Коли ми розробляємо веб‑застосунок на Spring — нам потрібно перевіряти, чи правильно він працює. Для цього є чудовий інструмент MockMvc. Уявіть, що ваш застосунок — це сучасне кафе. У звичайній ситуації, щоб протестувати роботу, потрібно запустити весь заклад: кухню, зал, посадити офіціантів. Це як запуск повноцінного сервера — довго і складно. MockMvc — це якби ви зробили мініатюрну копію кафе з одним кухарем і віконцем видачі. Через це вікно можна робити замовлення (відправляти запити) і отримувати готові страви (відповіді), не запускаючи весь заклад повністю. У світі Spring це означає, що ми можемо тестувати застосунок в полегшеному режимі — без повноцінного сервера і підключення до бази даних.


Підготовка оточення для тестів

Спочатку переконаємось, що ми підключили всі необхідні залежності для тестування. У вашому pom.xml (якщо ви використовуєте Maven) або build.gradle (якщо Gradle) мають бути вказані залежності для 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 вже вбудований у Spring Boot Starter Test, тож додаткових залежностей не потрібно.


Просте тестування REST API з MockMvc

Вхідні дані

Припустимо, у нас є REST‑контролер для керування сутностями "Продукт":


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

    @GetMapping("/{id}")
    public ResponseEntity<Product> getProductById(@PathVariable Long id) {
        // Це спрощена заглушка. У реальному житті тут буде виклик сервісу.
        if (id == 1L) {
            return ResponseEntity.ok(new Product(1L, "Кава", 5.0));
        }
        return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
    }
}

І у нас є сутність Product:


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

    // Конструктори, геттери та сеттери.
    public Product(Long id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    // Геттери та сеттери
    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;
    }
}

Пишемо тести

Тепер переходимо до написання тестів для ProductController. Ми хочемо переконатися, що:

  1. Якщо ми запитуємо ресурс з існуючим ID, то отримуємо коректний результат.
  2. Якщо ресурс з вказаним ID не існує, повертається статус 404.

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

    // Конструктори, геттери та сеттери.
    public Product(Long id, String name, Double price) {
        this.id = id;
        this.name = name;
        this.price = price;
    }

    // Геттери та сеттери
    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. Анотація @WebMvcTest: вказує, що ми будемо тестувати тільки шар контролерів. Spring автоматично підніме мінімальне необхідне оточення.
  2. Метод mockMvc.perform(): емуляє HTTP‑запит. Тут ми вказуємо шлях (/api/products/1) і метод (GET).
  3. Методи andExpect(): допомагають перевірити, що застосунок повертає очікувану відповідь. Ми можемо перевіряти:
    • Статус відповіді (isOk(), isNotFound() та інші).
    • Тип контенту (contentType()).
    • Вміст JSON‑відповіді (jsonPath()).

Тестування POST‑запитів

Тепер додамо в наш контролер метод для створення продукту:

@PostMapping
public ResponseEntity<Product> createProduct(@RequestBody Product product) {
    product.setId(2L); // Заглушка: завжди повертаємо один і той же ID
    return ResponseEntity.status(HttpStatus.CREATED).body(product);
}

Напишемо тест для цього методу. Ми хочемо переконатися, що:

  1. POST‑запит з коректними даними створює продукт і повертає статус 201 (Created).
  2. У тілі відповіді повертається створений продукт.

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

    mockMvc.perform(post("/api/products") // Емулюємо POST‑запит
            .contentType(MediaType.APPLICATION_JSON) // Вказуємо, що тіло запиту у форматі JSON
            .content(newProductJson)) // Передаємо JSON‑дані
            .andExpect(status().isCreated()) // Очікуємо статус 201 Created
            .andExpect(content().contentType(MediaType.APPLICATION_JSON)) // Відповідь теж JSON
            .andExpect(jsonPath("$.id").value(2)) // Перевіряємо ID
            .andExpect(jsonPath("$.name").value("Чай")) // Перевіряємо назву продукту
            .andExpect(jsonPath("$.price").value(3.5)); // Перевіряємо ціну продукту
}

Часті помилки та особливості

  1. Помилка "No qualifying bean of type '...' found"
    При використанні @WebMvcTest у тестовому оточенні піднімаються тільки контролери. Якщо у вашому контролері є залежності від сервісів або інших компонентів, не забудьте замокати їх за допомогою Mockito:
    @MockBean
    private ProductService productService;
    
  2. Некоректне використання @Autowired
    Завжди використовуйте правильні анотації (@Autowired або @MockBean) для залежності.
  3. JSON‑формат у запитах
    Переконайтесь, що відправлені JSON‑дані в тестах коректні. Використовуйте contentType(MediaType.APPLICATION_JSON).
  4. Проблеми з jsonPath
    Рекомендується використовувати онлайн‑валідатори JSONPath, щоб переконатися, що ваш шлях вказаний правильно.

На цьому етапі ми навчилися тестувати REST API з використанням MockMvc. Ці знання допоможуть вам не тільки виявляти баґи на ранніх етапах розробки, але й упевнено проходити співбесіди, де можуть попросити продемонструвати роботу з MockMvc.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ