MSW — API mock qilish Next.js da
Muammodan boshlaylik
Ilova tashqi API larga bog'liq: valyuta kurslari, yetkazib berish xizmati, to'lov tizimi, ob-havo. Testlarda:
- Haqiqiy API sekin va ba'zan ishlamaydi — testlar tasodifan qizil bo'ladi
- To'lov API ga test paytida haqiqiy so'rov — xavfli va pullik
- "API 500 qaytarsa nima bo'ladi?" — haqiqiy API ni ataylab buzib bo'lmaydi
- Backend jamoasi API ni hali tugatmagan — frontend kutib turadi
vi.mock('./api') — har bir modul uchun alohida mock, va u fetch qanday chaqirilishini tekshirmaydi.
MSW nima?
Mock Service Worker — tarmoq darajasida so'rovlarni ushlab, soxta javob qaytaradigan kutubxona. Kodingiz odatdagidek fetch qiladi — MSW uni "havoda" ushlaydi.
Kodingiz ──fetch('https://api.kurs.uz/usd')──▶ MSW ──▶ { kurs: 12650 }
(haqiqiy serverga bormaydi)
- Node.js da (Vitest, Next.js server) —
msw/node - Brauzerda — Service Worker orqali (
msw/browser) - Bir xil handler lar — testlarda, development da, Storybook da
Hayotiy o'xshatma
Kino suratga olish. Haqiqiy portlash o'rniga — maxsus effektlar. Aktyor xuddi haqiqiydek harakat qiladi, kamera xuddi haqiqiydek suratga oladi — lekin hech kim xavf ostida emas va sahnani istalgancha takrorlash mumkin.
O'rnatish
npm install -D msw
Handler lar
// mocks/handlers.ts
import { http, HttpResponse, delay } from 'msw'
export const handlers = [
http.get('https://api.kurs.uz/usd', () => {
return HttpResponse.json({ kurs: 12650, sana: '2026-11-08' })
}),
http.post('https://api.yetkazish.uz/narx', async ({ request }) => {
const { shahar } = (await request.json()) as { shahar: string }
return HttpResponse.json({ narx: shahar === 'Toshkent' ? 25000 : 45000 })
}),
http.get('https://api.dokon.uz/mahsulotlar/:id', ({ params }) => {
if (params.id === 'yoq') return HttpResponse.json({ xato: 'Topilmadi' }, { status: 404 })
return HttpResponse.json({ id: params.id, nomi: 'Choynak', narx: 120000 })
}),
]
Vitest da
// mocks/server.ts
import { setupServer } from 'msw/node'
import { handlers } from './handlers'
export const server = setupServer(...handlers)
// vitest.setup.ts
import '@testing-library/jest-dom/vitest'
import { beforeAll, afterEach, afterAll } from 'vitest'
import { server } from './mocks/server'
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
onUnhandledRequest: 'error'— mock qilinmagan so'rov ketsa, test xato beradi (tasodifan haqiqiy API ga bormaslik uchun)resetHandlers— bitta testdagi o'zgarish boshqasiga ta'sir qilmasin
Test
import { it, expect } from 'vitest'
import { http, HttpResponse } from 'msw'
import { server } from '@/mocks/server'
import { somdaNarx } from '@/lib/valyuta'
it("dollar narxini so'mga o'giradi", async () => {
expect(await somdaNarx(10)).toBe(126500)
})
it('API ishlamasa — zaxira kurs', async () => {
server.use(
http.get('https://api.kurs.uz/usd', () => HttpResponse.json({}, { status: 503 }))
)
expect(await somdaNarx(10)).toBe(125000) // zaxira kurs 12 500
})
server.use — faqat shu test uchun handler ni almashtirish. Xato holatlari, sekin javoblar (await delay(3000)), bo'sh natijalar — hammasini oson sinash.
Next.js server tomonida — development
Server Component va Route Handler lardagi fetch lar serverda ishlaydi. Development da ularni mock qilish uchun — instrumentation.ts:
// instrumentation.ts — loyiha ildizida
export async function register() {
if (process.env.NEXT_RUNTIME === 'nodejs' && process.env.API_MOCK === 'true') {
const { server } = await import('./mocks/server')
server.listen({ onUnhandledRequest: 'bypass' })
}
}
API_MOCK=true npm run dev
Backend tayyor bo'lmasa ham frontend ishlay oladi.
[!INFO] Next.js App Router da MSW ni server tomonida ishlatish hali to'liq barqaror emas: hot reload paytida modul qayta yuklanishi va Next.js ning o'z
fetchkengaytmalari bilan nozik muammolar uchrab turadi. Testlar uchun (Vitest) — ishonchli; development da server mock — rasmiy misollarga qarab, ehtiyotkorlik bilan.
Brauzerda
npx msw init public/ --save
// mocks/browser.ts
import { setupWorker } from 'msw/browser'
import { handlers } from './handlers'
export const worker = setupWorker(...handlers)
// app/MswProvider.tsx
'use client'
import { useEffect, useState } from 'react'
export function MswProvider({ children }: { children: React.ReactNode }) {
const [tayyor, setTayyor] = useState(process.env.NEXT_PUBLIC_API_MOCK !== 'true')
useEffect(() => {
if (process.env.NEXT_PUBLIC_API_MOCK === 'true') {
import('@/mocks/browser').then(({ worker }) =>
worker.start({ onUnhandledRequest: 'bypass' }).then(() => setTayyor(true))
)
}
}, [])
return tayyor ? <>{children}</> : null
}
Client komponentlardagi fetch lar (TanStack Query va h.k.) mock qilinadi. DevTools → Network da [MSW] belgisi ko'rinadi.
[!WARNING] MSW ni production bundle ga qo'shmang. Uni faqat environment o'zgaruvchisi bilan va dinamik
import()orqali yuklang — shunda mock kodi production ga tushmaydi.
Handler larni tartibli saqlash
mocks/
├── handlers/
│ ├── kurs.ts
│ ├── yetkazish.ts
│ └── index.ts
├── data/ ← soxta ma'lumotlar (fixtures)
├── server.ts
└── browser.ts
[!TIP] Mock javoblar haqiqiy API shakliga mos bo'lishi kerak — aks holda testlar o'tadi, production buziladi. API OpenAPI spetsifikatsiyasi bo'lsa, handler larni undan avtomatik yaratuvchi vositalar bor; yoki javob turlarini umumiy TypeScript tiplari bilan bog'lang.
Tez-tez uchraydigan xatolar
1. resetHandlers yo'q
Bitta testdagi server.use xatosi keyingi testlarga o'tadi — tasodifiy qizil testlar.
2. URL to'liq mos emas
Handler https://api.kurs.uz/usd, kod esa https://api.kurs.uz/usd/ ga so'raydi — ushlanmaydi. onUnhandledRequest: 'error' buni darhol ko'rsatadi.
3. Brauzerda mockServiceWorker.js yo'q
npx msw init public/ bajarilmagan.
Xulosa
MSW — tarmoq darajasida mock: kod odatdagidek fetch qiladi
http.get/post(url, resolver) → HttpResponse.json(data, { status })
Vitest: setupServer + listen / resetHandlers / close; onUnhandledRequest: 'error'
server.use — bitta test uchun xato, kechikish holatlari
Next.js server — instrumentation.ts (development, ehtiyotkorlik bilan)
Brauzer — setupWorker, npx msw init public/
Production ga tushmasin; mock shakli haqiqiy API ga mos
Keyingi bo'lim
65-dars: Environment Variables — .env, .env.local, .env.production
Deployment bo'limi: sozlamalar va maxfiy kalitlarni muhitlarga qarab boshqarish.