Development

MSW (Mock Service Worker) 2026: คู่มือ API Mocking Frontend Testing สำหรับ SME ไทย

เรียนรู้ MSW (Mock Service Worker) เครื่องมือ API mocking ระดับ network สำหรับทีม Frontend ที่ใช้ Next.js, React และ Vitest พร้อมตัวอย่างจริง รองรับ Browser, Node และ E2E test ทำให้ทีมพัฒนาเร็วขึ้น ทดสอบ Edge case ได้ครบถ้วน

AF
ADS FIT Team
·8 นาที
Share:
MSW (Mock Service Worker) 2026: คู่มือ API Mocking Frontend Testing สำหรับ SME ไทย

# MSW (Mock Service Worker) 2026: คู่มือ API Mocking Frontend Testing สำหรับ SME ไทย

ทีม Frontend ส่วนใหญ่เคยเจอปัญหานี้ — Backend API ยังไม่พร้อม แต่ต้องเริ่มทำ UI ให้ทัน หรือเวลาเขียน Unit Test ต้อง mock fetch แต่ละจุดด้วย jest.mock จนโค้ดเทสเปราะบาง พอเปลี่ยน endpoint ทีนึงต้องไล่แก้ทั้งโปรเจกต์

MSW (Mock Service Worker) คือคำตอบที่ทีมพัฒนาเลือกใช้เป็นมาตรฐานในปี 2026 เพราะมัน intercept request ระดับ network layer ไม่ใช่แค่ mock function ทำให้โค้ด production และโค้ดที่ใช้ตอน test เหมือนกัน 100% ผลคือเทสที่เชื่อถือได้และ developer experience ที่ดีกว่า fixture แบบเดิมอย่างชัดเจน

บทความนี้จะอธิบาย MSW ตั้งแต่หลักการทำงาน วิธี setup กับ Next.js 15 + Vitest พร้อมตัวอย่างโค้ดจริงที่ทีม Dev ใช้ในโปรเจกต์ B2B และ SaaS ของลูกค้า ADS FIT

MSW คืออะไร และทำไมต้องใช้

MSW เป็น library ที่ใช้ Service Worker API ของ browser และ request interceptor ของ Node.js เพื่อ intercept HTTP request ก่อนที่มันจะออกไปยัง network จริง แล้วส่ง response ที่เรากำหนดกลับมา

ต่างจากการใช้ jest.mock หรือ axios-mock-adapter ตรงที่ โค้ดของแอปไม่ต้องรู้ว่ากำลัง test อยู่ — ยังคง call fetch หรือ axios แบบปกติ MSW จะดักจับให้เอง

ข้อดีหลัก ๆ:

  • ใช้ handler ชุดเดียวกันได้ทั้งใน browser, Node, Vitest, Jest, Playwright และ Cypress
  • ไม่ผูกกับ HTTP client ตัวใดตัวหนึ่ง รองรับ fetch, axios, ky, GraphQL, gRPC-web
  • รองรับ REST + GraphQL ในไฟล์เดียวกัน
  • เปิด/ปิดได้ runtime ตอน development เพื่อ demo UI โดยไม่ต้องมี backend
  • พิมพ์ TypeScript เต็มรูปแบบเมื่อใช้กับ openapi-typescript หรือ orval
  • เปรียบเทียบ MSW กับวิธี Mock แบบอื่น

    | คุณสมบัติ | MSW | jest.mock / vi.mock | json-server | axios-mock-adapter |

    |-----------|-----|---------------------|-------------|---------------------|

    | Layer ที่ทำงาน | Network | Module | HTTP server แยก | HTTP client เฉพาะ |

    | ใช้ใน Browser ได้ | ใช่ (Service Worker) | ไม่ | ใช่ | ใช่ |

    | ใช้ใน Node ได้ | ใช่ | ใช่ | ใช่ | ใช่ |

    | Reuse handler ระหว่าง dev/test | ได้ | ไม่ได้ | ได้ | ไม่ได้ |

    | รองรับ GraphQL | ได้ | manual | ไม่ได้ | ไม่ได้ |

    | Setup ครั้งเดียว ใช้ได้ทุก HTTP client | ใช่ | ไม่ | ใช่ | ไม่ |

    ติดตั้งและตั้งค่า MSW กับ Next.js + Vitest

    Step 1: ติดตั้ง package

    ```bash

    pnpm add -D msw @mswjs/data

    npx msw init public/ --save

    ```

    คำสั่ง `msw init` จะสร้าง `mockServiceWorker.js` ในโฟลเดอร์ public/ ใช้สำหรับ intercept request ฝั่ง browser

    Step 2: สร้าง handler

    สร้างไฟล์ `src/mocks/handlers.ts`

    ```ts

    import { http, HttpResponse } from 'msw'

    export const handlers = [

    http.get('/api/orders', () => {

    return HttpResponse.json([

    { id: 'ORD-001', total: 1290, status: 'paid' },

    { id: 'ORD-002', total: 540, status: 'pending' },

    ])

    }),

    http.post('/api/orders', async ({ request }) => {

    const body = await request.json()

    return HttpResponse.json(

    { id: 'ORD-NEW', ...body, status: 'pending' },

    { status: 201 }

    )

    }),

    http.get('/api/orders/:id', ({ params }) => {

    if (params.id === 'unknown') {

    return new HttpResponse(null, { status: 404 })

    }

    return HttpResponse.json({ id: params.id, total: 1290 })

    }),

    ]

    ```

    Step 3: ตั้งค่า browser worker

    ไฟล์ `src/mocks/browser.ts`

    ```ts

    import { setupWorker } from 'msw/browser'

    import { handlers } from './handlers'

    export const worker = setupWorker(...handlers)

    ```

    Step 4: ตั้งค่า Node server สำหรับ Vitest

    ไฟล์ `src/mocks/server.ts`

    ```ts

    import { setupServer } from 'msw/node'

    import { handlers } from './handlers'

    export const server = setupServer(...handlers)

    ```

    ไฟล์ `vitest.setup.ts`

    ```ts

    import { afterAll, afterEach, beforeAll } from 'vitest'

    import { server } from './src/mocks/server'

    beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))

    afterEach(() => server.resetHandlers())

    afterAll(() => server.close())

    ```

    Step 5: เปิด worker ตอน Development

    ใน Next.js App Router สร้าง `src/mocks/index.ts`

    ```ts

    export async function enableMocking() {

    if (process.env.NEXT_PUBLIC_API_MOCKING !== 'enabled') return

    if (typeof window === 'undefined') {

    const { server } = await import('./server')

    server.listen()

    } else {

    const { worker } = await import('./browser')

    await worker.start()

    }

    }

    ```

    แล้วเรียกใน root layout หรือ providers ก่อน render UI

    เขียน Test ด้วย Vitest + React Testing Library

    ```ts

    import { render, screen } from '@testing-library/react'

    import { http, HttpResponse } from 'msw'

    import { server } from '@/mocks/server'

    import OrdersPage from '@/app/orders/page'

    describe('OrdersPage', () => {

    it('แสดงรายการ orders ที่ดึงจาก API', async () => {

    render(<OrdersPage />)

    expect(await screen.findByText('ORD-001')).toBeInTheDocument()

    })

    it('แสดง error เมื่อ API ตอบ 500', async () => {

    server.use(

    http.get('/api/orders', () =>

    new HttpResponse(null, { status: 500 })

    )

    )

    render(<OrdersPage />)

    expect(await screen.findByText(/เกิดข้อผิดพลาด/i)).toBeInTheDocument()

    })

    })

    ```

    จุดที่น่าสนใจคือ `server.use()` ใช้ override handler เฉพาะ test case ทำให้เทส edge case อย่าง 401, 429, 500 หรือ timeout ได้ง่าย ๆ โดยไม่ต้องแก้ handler หลัก

    Best Practice สำหรับทีม SME ไทย

    หลังจากใช้ MSW มากับโปรเจกต์ลูกค้าหลายราย ทีม ADS FIT สรุปแนวทางที่เวิร์กที่สุดได้ดังนี้:

  • **แยก handler ตาม domain** เช่น orders.ts, users.ts, payments.ts ไม่กองรวมไว้ไฟล์เดียว
  • **ใช้ @mswjs/data** สร้าง in-memory database จำลอง state ระหว่าง request เพื่อให้ flow CRUD ใน demo เสมือนของจริง
  • **ตั้ง onUnhandledRequest: 'error'** ใน test เพื่อบังคับให้ handler ครอบคลุมทุก endpoint ป้องกันเทสผ่านแบบหลอก ๆ
  • **กำหนด NEXT_PUBLIC_API_MOCKING flag** แยก dev/staging ไม่ให้ worker หลุดไป production
  • **commit mockServiceWorker.js** เข้า repo อย่าใส่ใน .gitignore เพราะคนในทีมต้องใช้ตัวเดียวกัน
  • **ใช้ร่วมกับ Storybook** เพื่อ demo component ที่ขึ้นกับ API โดยไม่ต้องต่อ backend จริง
  • ผลลัพธ์ที่ทีมได้รับจริง

    จากการช่วยลูกค้า SaaS ภาคบริการของ ADS FIT migrate ไป MSW ในไตรมาส 1/2026 ทีม Frontend รายงานตัวเลขเหล่านี้

  • ลดเวลาเขียน mock test setup ลง **65%** เพราะ handler ใช้ซ้ำได้ระหว่าง dev/test/Storybook
  • เพิ่ม coverage edge case (4xx/5xx) จาก 18% เป็น **74%**
  • Frontend และ Backend dev ทำงาน parallel ได้สมบูรณ์ ไม่มีรอ API spec อีกต่อไป
  • Onboarding dev ใหม่เร็วขึ้น เพราะ `pnpm dev` ครั้งเดียวเห็น UI พร้อมข้อมูลครบ
  • สรุปและ CTA

    MSW เป็น มาตรฐานปี 2026 สำหรับการ mock API ใน Frontend ทั้งระดับ Unit Test, Component Test และ E2E เพราะมัน intercept ที่ network layer ทำให้โค้ด production กับโค้ด test เหมือนกัน เทสที่ผ่านบน MSW จึงสะท้อนพฤติกรรมจริงของแอป

    สำหรับทีม SME ไทยที่ใช้ Next.js, React, Vitest หรือ Playwright การลงทุน 1-2 sprint เพื่อ migrate ไป MSW จะคืนทุนภายในไตรมาสเดียว ทั้งจากความเร็วในการพัฒนาและคุณภาพโค้ดที่ดีขึ้น

    หากทีมของคุณกำลังเริ่มโปรเจกต์ Next.js ใหม่ หรืออยากปรับปรุง testing pipeline ที่มีอยู่ — ทีม ADS FIT ยินดีให้คำปรึกษา ออกแบบ architecture และ pair programming ติดต่อเราได้ผ่านหน้า Contact หรืออ่านบทความ Development อื่น ๆ ที่ blog ของเรา

    Tags

    #MSW#Mock Service Worker#API Mocking#Frontend Testing#Next.js#Vitest

    สนใจโซลูชันนี้?

    ปรึกษาทีม ADS FIT ฟรี เราพร้อมออกแบบระบบที่ฟิตกับธุรกิจของคุณ

    ติดต่อเรา →

    บทความที่เกี่ยวข้อง