Тести компонентів, що завантажують дані, не повинні ходити в справжній API: повільно, нестабільно, залежить від стану бази. Підмінити fetch через vi.mock можна, але тоді тест прив'язаний до того, як код робить запит.
MSW (Mock Service Worker) перехоплює запити на рівні мережі: компонент викликає звичайний fetch чи axios, а відповідь надходить з обробника тесту.
// src/test/handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('/api/vacancies', () =>
HttpResponse.json([{ id: 1, title: 'Laravel-розробник' }]),
),
http.post('/api/vacancies/:id/apply', async ({ params, request }) => {
const body = await request.json();
return HttpResponse.json({ id: params.id, email: body.email }, { status: 201 });
}),
];
// src/test/setup.ts
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
Інший сценарій в окремому тесті - перевизначити обробник:
test('показує помилку сервера', async () => {
server.use(http.get('/api/vacancies', () => new HttpResponse(null, { status: 500 })));
render(<VacancyList />);
expect(await screen.findByRole('alert')).toHaveTextContent('Не вдалося завантажити');
});
resetHandlers() після тесту повертає типові обробники - сценарії не «протікають» між тестами.
Переваги:
- тест не знає про спосіб запиту - перехід з
fetchна axios чи TanStack Query не ламає тести; - ті самі обробники працюють у браузері (через Service Worker) - для розробки фронтенду без готового бекенду, в Storybook і в браузерних тестах;
onUnhandledRequest: 'error'- тест падає на запиті, для якого немає обробника, замість тихого звернення в мережу.
Що варто знати:
- відносні URL (
/api/...) у середовищі jsdom розв'язуються відносноlocationтесту; - затримки й мережеві помилки -
await delay(1000)іHttpResponse.error()для перевірки станів завантаження й обриву з'єднання; - перевіряти запит: тіло й заголовки читаються в обробнику (
await request.json()), тож можна переконатися, що форма відправила правильні дані.