Mock Server Pattern — это подход к тестированию, при
котором реальные HTTP-запросы заменяются заранее определёнными ответами
(моками). Он позволяет изолировать фронтенд от бэкенда, ускоряет тесты и
делает их предсказуемыми. В Playwright этот паттерн реализуется через
перехват сетевых запросов с помощью API page.route().
Базовый принцип заключается в том, чтобы перехватывать запросы на определённые URL и подставлять ответ, который ожидается в тесте. Пример:
import { test, expect } from '@playwright/test';
test('Mock API response', async ({ page }) => {
await page.route('**/api/users', route =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify([{ id: 1, name: 'Alice' }])
})
);
await page.goto('https://example.com/users');
const userName = await page.textContent('.user-name');
expect(userName).toBe('Alice');
});
Ключевые моменты:
**/api/users позволяет
перехватывать любые запросы к этому endpoint.route.fulfill() полностью заменяет ответ сервера,
включая статус, заголовки и тело.Для упрощения поддержки большого количества сценариев часто используют JSON-файлы с ответами. Это делает тесты более читаемыми и масштабируемыми:
import fs from 'fs';
import { test } from '@playwright/test';
test('Load users from mock file', async ({ page }) => {
const mockData = fs.readFileSync('mocks/users.json', 'utf-8');
await page.route('**/api/users', route =>
route.fulfill({
status: 200,
contentType: 'application/json',
body: mockData
})
);
await page.goto('https://example.com/users');
});
Преимущества такого подхода:
Иногда требуется возвращать ответы, зависящие от запроса. Playwright позволяет реализовать динамическое мокирование:
await page.route('**/api/users/*', route => {
const userId = route.request().url().split('/').pop();
route.fulfill({
status: 200,
contentType: 'application/json',
body: JSON.stringify({ id: Number(userId), name: `User ${userId}` })
});
});
Особенности:
route.request() позволяет анализировать
URL, метод и тело запроса.Mock Server Pattern не ограничивается только успешными ответами. Можно симулировать задержки, таймауты и ошибки:
await page.route('**/api/users', async route => {
await new Promise(resolve => setTimeout(resolve, 1000));
route.fulfill({
status: 500,
contentType: 'application/json',
body: JSON.stringify({ error: 'Internal Server Error' })
});
});
Использование задержек и ошибок позволяет:
page.waitForResponse()Mock Server Pattern хорошо сочетается с методами ожидания Playwright, что позволяет убедиться, что приложение корректно обрабатывает ответ:
const [response] = await Promise.all([
page.waitForResponse('**/api/users'),
page.click('button.load-users')
]);
expect(response.status()).toBe(200);
const data = await response.json();
expect(data.length).toBeGreaterThan(0);
Преимущество: проверка как UI, так и фактического ответа одновременно.
Для крупных проектов удобно создавать отдельный слой моков:
mocks/
├─ users.json
├─ products.json
└─ orders.json
И подключать их динамически в тестах:
import * as usersMock from '../mocks/users.json';
await page.route('**/api/users', route =>
route.fulfill({ status: 200, contentType: 'application/json', body: JSON.stringify(usersMock) })
);
Рекомендации по организации:
Playwright позволяет комбинировать Mock Server Pattern с логированием запросов. Это помогает проверять, какие запросы реально уходят на сервер, даже если большинство ответов подменены:
page.on('request', request => {
console.log('Request:', request.method(), request.url());
});
Это особенно полезно при тестировании сложных сценариев с несколькими запросами, где важно убедиться, что фронтенд отправляет корректные данные.
Этот паттерн является фундаментальной практикой для надёжного E2E тестирования в Playwright и позволяет создавать предсказуемые, стабильные и масштабируемые тестовые сценарии.