Моки и стабы для HTTP-запросов

В автоматизированном тестировании веб-приложений важную роль играет контроль над сетевыми запросами. Cypress предоставляет мощные инструменты для работы с моками и стабами, что позволяет тестировать приложение изолированно, без зависимости от реального бэкенда.

Различие между моками и стабами

  • Стаб (stub) — подмена части функционала, чаще всего функции или метода, с целью контролировать её поведение. В контексте HTTP-запросов это означает перехват вызова и возврат заранее определённого ответа.
  • Мок (mock) — более сложная концепция, которая включает проверку вызовов: сколько раз была вызвана функция, с какими параметрами, и корректность взаимодействия.

В Cypress основная работа ведётся со стабами, которые могут использоваться для имитации ответов сервера.

Перехват и подмена запросов

Cypress использует команду cy.intercept() для перехвата HTTP-запросов. Она заменяет устаревший cy.route() и предоставляет гибкий способ контроля над запросами.

Пример базового стаба GET-запроса:

cy.intercept('GET', '/api/users', {
  statusCode: 200,
  body: [
    { id: 1, name: 'Иван' },
    { id: 2, name: 'Мария' }
  ]
}).as('getUsers');

cy.visit('/users');
cy.wait('@getUsers');

Ключевые моменты:

  • Паттерн URL может быть строкой или регулярным выражением.
  • as() задаёт алиас, который упрощает ожидание запроса через cy.wait().
  • Ответ можно настроить с любым статусом, заголовками и телом.

Стабы POST, PUT и DELETE запросов

Моки полезны не только для GET. Любой тип запроса можно подменить.

cy.intercept('POST', '/api/users', (req) => {
  req.reply({
    statusCode: 201,
    body: { id: 3, name: req.body.name }
  });
}).as('createUser');

cy.get('form').submit();
cy.wait('@createUser');

Особенности:

  • req.body позволяет использовать данные из запроса для формирования ответа.
  • Можно имитировать ошибки сервера, передавая статус 4xx или 5xx, что позволяет тестировать обработку исключений в приложении.

Динамические ответы и задержки

Cypress позволяет создавать более реалистичные ответы, добавляя задержки или изменяя содержимое на основе входных данных:

cy.intercept('GET', '/api/orders', (req) => {
  req.reply((res) => {
    res.delay(500); // имитация сетевой задержки
    res.send({
      statusCode: 200,
      body: [{ id: 101, total: 250 }]
    });
  });
}).as('getOrders');
  • Метод res.delay() полезен для тестирования загрузочных индикаторов.
  • res.send() позволяет полностью контролировать статус, заголовки и тело ответа.

Проверка вызовов и параметров запросов

Используя стабы, можно проверять, как приложение взаимодействует с API:

cy.intercept('PUT', '/api/users/*').as('updateUser');

cy.get('input[name="name"]').clear().type('Алексей');
cy.get('button.save').click();

cy.wait('@updateUser').its('request.body').should('deep.equal', {
  name: 'Алексей'
});
  • its('request.body') позволяет проверить тело запроса.
  • Аналогично можно проверять заголовки (request.headers) и URL-параметры (request.url).

Сложные сценарии: последовательные ответы

Можно настроить разные ответы на повторяющиеся запросы, что полезно при тестировании пагинации или шагов с прогрессом:

cy.intercept('GET', '/api/messages', [
  { id: 1, text: 'Привет' },
  { id: 2, text: 'Как дела?' }
]).as('firstFetch');

cy.intercept('GET', '/api/messages', [
  { id: 3, text: 'Новое сообщение' }
]).as('secondFetch');
  • Первый вызов вернёт один набор данных, второй — другой.
  • Позволяет полностью управлять тестовыми сценариями без зависимости от реального сервера.

Использование фиктивных данных (fixtures)

Cypress поддерживает работу с файлами фикстур. Это удобно для больших объёмов тестовых данных:

cy.fixture('users.json').then((users) => {
  cy.intercept('GET', '/api/users', users).as('getUsers');
});
  • Файл users.json хранится в папке cypress/fixtures.
  • Облегчает поддержку тестовых данных и повторное использование между тестами.

Советы по применению моков и стабов

  • Всегда даёт контроль над сетевыми запросами, снижая зависимость от бэкенда.
  • Упрощает тестирование ошибок и граничных случаев.
  • Стабы должны имитировать реалистичные ответы для адекватного тестирования UI.
  • Избегать использования реального API для интеграционных тестов, если важно воспроизводимое окружение.
  • Использовать алиасы для упрощения cy.wait() и проверки последовательности запросов.

Моки и стабы в Cypress позволяют создавать надёжные, повторяемые и быстрые тесты, обеспечивая полный контроль над HTTP-взаимодействием, проверку данных и моделирование сетевых условий.