Testing / Mocking

MSW i API Mocking w React

MSW 2.0 (http/HttpResponse, Browser+Node), Vitest+RTL integration, Storybook mocking i contract testing z Pact.

MSW 2.0
Network-level
Storybook
Story mocking
Pact
Contract tests
Vitest+RTL
Node testing

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ŚrodowiskoAPIIntegracjaKiedy
MSW 2.0Browser + Nodehttp, HttpResponse (native fetch)RTL, Vitest, Storybook, PlaywrightStandard — najlepszy wybór 2024
nockNode.js onlynock(url).get(path).reply()Jest, Mocha, VitestNode.js only, legacy projects
fetch-mockBrowser + NodefetchMock.get(url, response)Jest, VitestProsty fetch mocking, minimalna setup
axios-mock-adapterBrowser + Nodemock.onGet('/url').reply()DowolneProjekty z Axios, stary pattern
PactBrowser + NodePactV3 consumer/providerPact Broker, CI/CDContract testing microservices
WireMockSerwer (Java)JSON stub mappingsDowolne (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.

Kontakt

Skontaktuj się z nami

Porozmawiajmy o Twoim projekcie. Bezpłatna wycena w ciągu 24 godzin.

Wyślij zapytanie

Bezpłatna wycena w 24h
Bez zobowiązań
Indywidualne podejście
Ekspresowa realizacja

Telefon

+48 790 814 814

Pon-Pt: 9:00 - 18:00

Email

adam@fotz.pl

Odpowiadamy w ciągu 24h

Adres rejestrowy

Poznańska 117/11

62-023 Kamionki · obsługa zdalna

Godziny pracy

Pon - Pt9:00 - 18:00
Sob - NdzZamknięte

Wolisz porozmawiać?

Zadzwoń teraz i porozmawiaj z naszym specjalistą o Twoim projekcie.

Zadzwoń teraz