MSW i API Mocking w React
MSW 2.0 (http/HttpResponse, Browser+Node), Vitest+RTL integration, Storybook mocking i contract testing z Pact.
6 narzędzi API mocking — porównanie
MSW, nock, fetch-mock, axios-mock-adapter, Pact i WireMock — środowisko, API, integracja i kiedy użyć.
| Narzędzie | Środowisko | API | Integracja | Kiedy |
|---|---|---|---|---|
| MSW 2.0 | Browser + Node | http, HttpResponse (native fetch) | RTL, Vitest, Storybook, Playwright | Standard — najlepszy wybór 2024 |
| nock | Node.js only | nock(url).get(path).reply() | Jest, Mocha, Vitest | Node.js only, legacy projects |
| fetch-mock | Browser + Node | fetchMock.get(url, response) | Jest, Vitest | Prosty fetch mocking, minimalna setup |
| axios-mock-adapter | Browser + Node | mock.onGet('/url').reply() | Dowolne | Projekty z Axios, stary pattern |
| Pact | Browser + Node | PactV3 consumer/provider | Pact Broker, CI/CD | Contract testing microservices |
| WireMock | Serwer (Java) | JSON stub mappings | Dowolne (HTTP) | Enterprise, Java teams, shared stubs |
Często zadawane pytania
Co to jest MSW (Mock Service Worker) i jak działa?
MSW (Mock Service Worker): biblioteka do mockowania HTTP requestów. Działa na poziomie sieciowym (nie patch fetch). Browser: Service Worker przechwytuje requesty. Node.js: interceptor requestów. Instalacja: npm install msw --save-dev. npx msw init public/ --save (dla przeglądarki). Wersja 2.0 (2023): nowe API. http.get zamiast rest.get. HttpResponse.json() zamiast res(ctx.json()). Native Fetch API. Handlers: import {http, HttpResponse} from 'msw'. const handlers = [http.get('/api/users', () => {return HttpResponse.json([{id: 1, name: 'Adam'}])}), http.post('/api/users', async ({request}) => {const body = await request.json(); return HttpResponse.json({...body, id: 2}, {status: 201})})]. Browser setup: import {setupWorker} from 'msw/browser'. const worker = setupWorker(...handlers). worker.start(). Node.js setup (testy): import {setupServer} from 'msw/node'. const server = setupServer(...handlers). beforeAll(() => server.listen()). afterEach(() => server.resetHandlers()). afterAll(() => server.close()). Dlaczego MSW: interceptuje na poziomie sieci (jak realne requesty). Działa w Browser + Node. Jeden zestaw handlerów dla testów + development. Nie wymaga zmiany kodu aplikacji. Obsługuje REST i GraphQL. TypeScript support natywny. Alternatywy: nock (Node only). axios-mock-adapter. fetch-mock. Jest spyOn(global, 'fetch'). MSW jest bardziej realistyczny.
MSW 2.0 — co zmieniło się w API i jak migrować?
MSW 1.x (stare API): import {rest} from 'msw'. rest.get('/users', (req, res, ctx) => {return res(ctx.json([...]), ctx.status(200))}). Problemy: ctx API — nieintuicyjne. Nie-native fetch. Trudne do typowania requestów. MSW 2.0 (nowe API): import {http, HttpResponse, graphql} from 'msw'. http.get('/users', () => {return HttpResponse.json([...])}). http.post('/users', async ({request}) => {const body = await request.json()}). Kluczowe zmiany v2: rest -> http. ctx.json() -> HttpResponse.json(). ctx.status() -> drugi argument HttpResponse. ctx.delay() -> usunięte, użyj delay() import. resolver params: ({request, params, cookies}). request: natywny Request. params: path parameters. cookies: cookies. Typy TypeScript: http.get('/users/:id', ({params}) => {const {id} = params}). HTTP Response z delay: import {delay} from 'msw'. await delay(500). Passthrough (nie mockuj): import {passthrough} from 'msw'. return passthrough(). Error handling: HttpResponse.json({error: 'Not found'}, {status: 404}). GraphQL mocking: graphql.query('GetUser', ({variables}) => {return HttpResponse.json({data: {user: {id: variables.id}}})}). graphql.mutation('CreateUser', ...). Migracja v1->v2: automatyczny codemod (msw-codemods). Większość zmian mechanicznych. Sprawdź custom resolvers.
Testing z MSW + React Testing Library + Vitest?
Setup (Vitest + RTL + MSW): npm install msw @testing-library/react @testing-library/jest-dom vitest --save-dev. vitest.config.ts: environment: 'jsdom'. setupFiles: ['./src/test/setup.ts']. setup.ts: import '@testing-library/jest-dom'. import {server} from './mocks/server'. beforeAll(() => server.listen({onUnhandledRequest: 'error'})). afterEach(() => server.resetHandlers()). afterAll(() => server.close()). handlers.ts: export const handlers = [http.get('/api/todos', () => {return HttpResponse.json([{id: 1, title: 'Buy milk', done: false}])})]. server.ts: import {setupServer} from 'msw/node'. export const server = setupServer(...handlers). Test komponentu: it('displays todos from API', async () => {render(TodoList). await waitFor(() => screen.getByText('Buy milk')). expect(screen.getByText('Buy milk')).toBeInTheDocument()}). Override handler w teście: server.use(http.get('/api/todos', () => {return HttpResponse.json([], {status: 500})})). Testuj error state. Testuj loading state: render(TodoList). expect(screen.getByText('Loading...')).toBeInTheDocument(). await waitFor(() => screen.getByText('Buy milk')). React Query + MSW: QueryClientProvider w teście. QueryClient z retry: 0 (szybkie testy). MSW zwraca dane -> React Query cachuje -> komponent renderuje. Async tests: await screen.findByText('text') zamiast waitFor. findBy* zawiera wbudowany waitFor.
MSW w Storybook — development mocking?
MSW + Storybook: msw-storybook-addon. Mockuj API w Storiesach. Każda story może mieć własne handlery. Instalacja: npm install msw-storybook-addon --save-dev. .storybook/preview.ts: import {initialize, mswLoader} from 'msw-storybook-addon'. initialize(). export const loaders = [mswLoader]. Story z MSW: import {http, HttpResponse} from 'msw'. export const Success: Story = {parameters: {msw: {handlers: [http.get('/api/user', () => {return HttpResponse.json({name: 'Adam', role: 'admin'})})]}}. export const Error: Story = {parameters: {msw: {handlers: [http.get('/api/user', () => {return HttpResponse.json({error: 'Unauthorized'}, {status: 401})})]}}. Korzyści: visual testing różnych stanów API. Dokumentacja interaktywna z realnymi danymi. Brak potrzeby backendu do development. Chromatic: visual regression testing. Screenshot stories z różnymi API stanami. CI pipeline testing. Storybook 8 nowości: Storybook 8 (2024). Vitest integration (--vitest mode). Chromatic TurboSnap. Szybsze builds. React Server Components support. MSW w development (browser): index.tsx/main.tsx: if (process.env.NODE_ENV === 'development') {const {worker} = await import('./mocks/browser'); await worker.start({onUnhandledRequest: 'bypass'})}. Zakomentowane API calls w .env.local? Lepiej: MSW conditional start. Debugowanie: MSW DevTools (unofficial). Network tab w DevTools — requesty widoczne jako przez SW. console.log w handlerach. Dodaj 'MSW: ' prefix do logów.
Contract Testing z Pact — zaawansowane API mocking?
Contract Testing: consumer definiuje kontrakt co oczekuje od API. Provider weryfikuje czy spełnia kontrakt. Automatyczna weryfikacja kompatybilności. Pact: najpopularniejsza biblioteka contract testing. @pact-foundation/pact. Consumer-driven contracts. Pact Broker — serwer do przechowywania kontraktów. Consumer test (React app -> API): import {PactV3, MatchersV3} from '@pact-foundation/pact'. const {string, integer} = MatchersV3. Pact opisuje: oczekiwany request. Oczekiwana response. Pact generuje kontrakt JSON. Provider verification (backend Node.js): @pact-foundation/pact (provider side). Wczytaj kontrakt z Pact Broker. Uruchom testy przeciwko realnemu serwerowi. Kiedy Pact: microservices. Niezależne deploymenty. Różne teams. CI/CD. Pact vs MSW: MSW — mocking w unit/integration tests. Pact — contract testing między services. Komplementarne, nie konkurencyjne. Consumer-Driven Contract (CDC): consumer prowadzi zmiany API. Provider musi spełnić kontrakt. Bezpieczeństwo przed breaking changes. Pact Broker: publiczny SaaS lub self-hosted. Przechowuje kontrakty między wersje. Can-I-Deploy: weryfikuj przed deployment. Matryce kompatybilności. WireMock: Java-based API mocking. Stub mappings w JSON. Dobry dla Java + TS teams. Karate DSL: BDD + API testing + mocking. Scenariusze w Gherkin. Szczególnie dla QA teams.
Powiązane artykuły
Skontaktuj się z nami
Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.
Wyślij zapytanie
Telefon
+48 790 814 814
Pon-Pt: 9:00 - 18:00
adam@fotz.pl
Odpowiadamy w ciągu 24h
Adres
Plac Wolności 16
61-739 Poznań
Godziny pracy
Wolisz porozmawiać?
Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.
Zadzwoń teraz