MSW (Mock Service Worker) представляет собой инструмент для перехвата HTTP-запросов на уровне браузера или Node.js и подмены их ответов. В сочетании с Vue Test Utils он позволяет изолированно тестировать компоненты, взаимодействующие с API, без необходимости настоящих сетевых вызовов. Это обеспечивает стабильность тестов, предсказуемость результатов и возможность моделировать различные состояния сервера.
Для работы с MSW необходимо установить пакет через npm:
npm install msw --save-dev
Создание обработчиков запросов (handlers) осуществляется с помощью
функции rest:
import { rest } from 'msw';
export const handlers = [
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json([
{ id: 1, name: 'Иван' },
{ id: 2, name: 'Мария' },
])
);
}),
rest.post('/api/users', (req, res, ctx) => {
const { name } = req.body;
return res(
ctx.status(201),
ctx.json({ id: Math.floor(Math.random() * 1000), name })
);
}),
];
Для браузерного окружения используется сервис-воркер:
import { setupWorker } from 'msw';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
worker.start();
В Node.js среде (например, при запуске Jest) применяется
setupServer:
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
// Настройка Jest хуков
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
Vue Test Utils предоставляет методы для монтирования компонентов и симуляции взаимодействия пользователя. При этом любые сетевые запросы, инициируемые компонентом, будут перехвачены MSW.
Пример теста компонента UserList.vue:
import { mount } from '@vue/test-utils';
import UserList from '@/components/UserList.vue';
import { server } from '@/mocks/server';
import { rest } from 'msw';
describe('UserList', () => {
it('отображает список пользователей', async () => {
const wrapper = mount(UserList);
// Ждем завершения асинхронного обновления компонента
await wrapper.vm.$nextTick();
const items = wrapper.findAll('li');
expect(items).toHaveLength(2);
expect(items[0].text()).toBe('Иван');
expect(items[1].text()).toBe('Мария');
});
it('обрабатывает ошибку сервера', async () => {
server.use(
rest.get('/api/users', (req, res, ctx) => {
return res(ctx.status(500));
})
);
const wrapper = mount(UserList);
await wrapper.vm.$nextTick();
expect(wrapper.text()).toContain('Ошибка загрузки пользователей');
});
});
Ключевые моменты:
server.use позволяет временно переопределить
обработчики для конкретного теста.await wrapper.vm.$nextTick() или
flushPromises.Vue-компоненты часто используют fetch или axios для
получения данных. MSW полностью поддерживает оба подхода.
Пример с axios:
import axios from 'axios';
export async function fetchUsers() {
const response = await axios.get('/api/users');
return response.data;
}
Тестирование:
import { fetchUsers } from '@/api/users';
it('возвращает список пользователей через axios', async () => {
const users = await fetchUsers();
expect(users).toEqual([
{ id: 1, name: 'Иван' },
{ id: 2, name: 'Мария' },
]);
});
MSW перехватывает axios-запросы точно так же, как обычный fetch, обеспечивая универсальность.
MSW позволяет эмулировать:
ctx.status(200)),ctx.status(500)),ctx.delay(1000)),Пример теста с задержкой:
server.use(
rest.get('/api/users', (req, res, ctx) => {
return res(
ctx.delay(500),
ctx.status(200),
ctx.json([{ id: 1, name: 'Иван' }])
);
})
);
Такой подход позволяет проверять состояние загрузки
(loading) в компонентах и корректное отображение
индикаторов прогресса.
Сложные компоненты, которые зависят от нескольких API, могут тестироваться через массив обработчиков:
server.use(
rest.get('/api/users', (req, res, ctx) => res(ctx.json([{ id: 1, name: 'Иван' }]))),
rest.get('/api/posts', (req, res, ctx) => res(ctx.json([{ id: 101, title: 'Пост 1' }])))
);
Компонент может одновременно отображать пользователей и посты. Использование MSW позволяет эмулировать сценарии с разными комбинациями ответов API, включая ошибки или частичные данные.
MSW поддерживает логирование запросов и ответов, что облегчает отладку тестов:
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
server.events.on('request:start', (req) => {
console.log('Запрос:', req.url.href);
});
server.events.on('response:mocked', (res, req) => {
console.log('Мок-ответ для', req.url.href, 'Статус:', res.status);
});
Это позволяет отслеживать, какие запросы были перехвачены, и убедиться в корректной работе обработчиков.
server.use с
переопределением обработчиков на уровне конкретного теста.flushPromises или nextTick.Использование MSW вместе с Vue Test Utils делает тестирование компонентов, взаимодействующих с API, надежным и предсказуемым, упрощает управление асинхронностью и моделирование различных сценариев сервера.