DEV Community

Cover image for Giải pháp thay thế MSW: Khi nào nên dùng nền tảng giả lập API hoàn chỉnh
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

Giải pháp thay thế MSW: Khi nào nên dùng nền tảng giả lập API hoàn chỉnh

Nếu bạn viết kiểm thử frontend, có lẽ bạn đã dùng hoặc nghe đến Mock Service Worker (MSW). MSW rất mạnh để chặn request trong trình duyệt và Node, đặc biệt cho unit test và component test. Bài viết này đi thẳng vào cách dùng MSW hiệu quả, giới hạn khi mock cần mở rộng cho nhiều đội/ngôn ngữ, và khi nào nên bổ sung một nền tảng tạo mock API được lưu trữ.

Dùng thử Apidog ngay hôm nay

Mock Service Worker là gì?

Mock Service Worker là thư viện JavaScript dùng để chặn request mạng tại nguồn.

  • Trong trình duyệt, MSW đăng ký một Service Worker để bắt fetchXMLHttpRequest.
  • Trong Node, MSW vá lớp request để cùng một bộ handler có thể chạy trong Jest, Vitest hoặc môi trường test Node.
  • Bạn định nghĩa handler theo method và path, sau đó trả về response mong muốn.

MSW overview

Điểm mạnh của MSW là ứng dụng vẫn gọi API như thật. Bạn không cần stub fetch, không cần thay đổi HTTP client, và không cần viết nhánh logic riêng cho môi trường test. MSW đứng giữa request và network để trả response mock.

Bạn có thể xem thêm mã nguồn MSW trên GitHub để hiểu cách lớp chặn hoạt động.

Ví dụ handler cơ bản:

import { http, HttpResponse } from 'msw'

export const handlers = [
  http.get('/api/users/:id', ({ params }) => {
    return HttpResponse.json({
      id: params.id,
      name: 'Ada Lovelace',
    })
  }),
]
Enter fullscreen mode Exit fullscreen mode

Sau đó dùng handler này trong test hoặc môi trường dev. Mock nằm cạnh code, được version control cùng test, và chạy ở bất cứ nơi nào JavaScript chạy.

Khi nào nên dùng MSW?

MSW phù hợp nhất khi mock và code tiêu thụ mock nằm trong cùng một codebase.

1. Unit test và component test

Bạn render component, để component gọi API thật qua fetch hoặc HTTP client, rồi MSW trả dữ liệu mẫu.

Ví dụ với React Testing Library:

import { render, screen } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import UserProfile from './UserProfile'

const server = setupServer(
  http.get('/api/users/:id', () => {
    return HttpResponse.json({
      id: '1',
      name: 'Ada Lovelace',
    })
  })
)

beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())

test('hiển thị tên người dùng', async () => {
  render(<UserProfile userId="1" />)

  expect(await screen.findByText('Ada Lovelace')).toBeInTheDocument()
})
Enter fullscreen mode Exit fullscreen mode

Cách này khác với việc mock trực tiếp HTTP client. Nếu bạn đang so sánh hai hướng tiếp cận, xem thêm bài về cách mock một lệnh gọi API trong Jest.

2. Phát triển frontend khi backend chưa sẵn sàng

Bạn có thể dựng UI trước, sau đó đổi handler để mô phỏng nhiều trạng thái:

http.get('/api/orders', () => {
  return HttpResponse.json([
    { id: 'ord_1', status: 'paid', total: 120 },
    { id: 'ord_2', status: 'pending', total: 80 },
  ])
})
Enter fullscreen mode Exit fullscreen mode

Mô phỏng lỗi:

http.get('/api/orders', () => {
  return new HttpResponse(null, { status: 500 })
})
Enter fullscreen mode Exit fullscreen mode

Mô phỏng trạng thái rỗng:

http.get('/api/orders', () => {
  return HttpResponse.json([])
})
Enter fullscreen mode Exit fullscreen mode

3. CI ổn định hơn

Test không gọi server thật, nên ít bị ảnh hưởng bởi:

  • network không ổn định
  • dữ liệu staging thay đổi
  • môi trường backend bị deploy lại
  • rate limit hoặc auth token hết hạn

4. Một ngôn ngữ, một đội, một repository

Nếu đội viết mock cũng là đội tiêu thụ mock, giữ handler MSW trong repo là cách đơn giản và hiệu quả nhất.

Khi MSW bắt đầu gặp giới hạn

Điểm mạnh của MSW là mock sống trong codebase. Nhưng khi mock cần được chia sẻ rộng hơn, chính điều này lại thành giới hạn.

Người tiêu thụ không dùng JavaScript

Handler của MSW là JavaScript. Nếu mobile app viết bằng Swift/Kotlin, hoặc backend integration test chạy bằng Go/Python, các đội đó không thể import handler MSW của frontend.

Khi đó, bạn thường phải viết lại mock ở từng stack. Điều này dễ làm response giữa các môi trường bị lệch nhau.

Một máy chủ mock không phụ thuộc ngôn ngữ giải quyết vấn đề này bằng cách cung cấp URL HTTP thật. Bất kỳ client nào gọi được HTTP đều dùng được mock.

Cần một URL mock dùng chung

MSW chạy trong một process cụ thể:

  • trong tab trình duyệt
  • trong test runner
  • trong dev server local

Nó không cung cấp một URL ổn định để QA, designer, mobile developer hoặc đối tác bên ngoài cùng truy cập.

Nếu nhiều người cần gọi cùng một endpoint mock, bạn cần một mock server được lưu trữ thay vì Service Worker gắn với môi trường local.

API được thiết kế từ OpenAPI/schema

Nếu đội bạn làm API design-first, bạn thường muốn:

  1. viết hoặc import OpenAPI schema
  2. sinh mock từ schema
  3. dùng mock để frontend/mobile phát triển song song
  4. đảm bảo mock không lệch hợp đồng API

MSW không tự sinh handler từ OpenAPI theo mặc định. Bạn phải tự viết handler. Cách này linh hoạt, nhưng cũng dễ khiến mock không còn khớp contract.

Bạn có thể xem thêm về hướng tiếp cận schema-first trong bài tạo mock API.

Cần dữ liệu động và thực tế ở quy mô lớn

Với MSW, response là thứ bạn tự code.

Ví dụ:

http.get('/api/users', () => {
  return HttpResponse.json([
    {
      id: '1',
      email: 'ada@example.com',
      createdAt: '2026-06-01T10:00:00Z',
    },
  ])
})
Enter fullscreen mode Exit fullscreen mode

Cách này ổn cho vài endpoint. Nhưng khi API có nhiều resource, nhiều field, nhiều trạng thái biên, bạn sẽ phải tự duy trì nhiều dữ liệu mẫu.

Các nền tảng mock API thường có khả năng sinh dữ liệu theo tên field, kiểu dữ liệu hoặc schema, giúp giảm công viết dữ liệu thủ công.

MSW so với nền tảng tạo mock API đầy đủ

Không có lựa chọn nào “tốt hơn” trong mọi trường hợp. MSW và nền tảng mock API giải quyết hai bài toán khác nhau.

Khả năng Mock Service Worker Nền tảng API được lưu trữ, ví dụ Apidog
Chạy trong unit/component test JS Có, nguyên bản Không, không phải thư viện test JS
Không phụ thuộc ngôn ngữ qua HTTP Không, chủ yếu cho JS Có, bất kỳ HTTP client nào
URL dùng chung cho toàn đội Không Có, mock server được lưu trữ
Tạo mock từ OpenAPI Thủ công Tự động từ schema
Dữ liệu thông minh/động Tự code Tích hợp sẵn
Sống trong repo cùng test Lưu trong project chia sẻ
Chi phí Miễn phí, mã nguồn mở Có gói miễn phí và gói trả phí

Tóm lại:

  • Dùng MSW cho unit test, component test và frontend local development.
  • Dùng nền tảng như Apidog khi mock cần được chia sẻ, không phụ thuộc ngôn ngữ hoặc sinh từ API schema.

Apidog là phần bổ sung, không phải thay thế trực tiếp cho MSW

Apidog không phải là thư viện JavaScript để import vào Jest hoặc Vitest. Vì vậy, nó không thay thế MSW trong unit test.

Thay vào đó, Apidog phù hợp với lớp mock dùng chung cho cả đội.

Một workflow thực tế:

  1. Thiết kế hoặc import API schema vào Apidog.
  2. Tạo mock endpoint từ schema.
  3. Chia sẻ URL mock cho frontend, mobile, QA hoặc backend.
  4. Dùng response mock để phát triển song song trước khi backend hoàn thiện.
  5. Tùy chỉnh rule cho các case như 500, dữ liệu rỗng hoặc edge case cụ thể.

Apidog mock API

Ví dụ phân chia trách nhiệm:

Frontend unit/component test
        ↓
      MSW

Cross-team mock / mobile / QA / demo
        ↓
 Hosted mock server từ Apidog
Enter fullscreen mode Exit fullscreen mode

Khi mock được tạo từ cùng schema với thiết kế và test API, bạn giảm rủi ro response mock bị lệch contract. Đây là điểm mà handler viết tay khó đảm bảo nếu dự án lớn dần.

Nếu muốn so sánh thêm các lựa chọn, xem bài tổng hợp các công cụ tạo mock API tốt nhất.

API mock tools

Một cách triển khai thực tế cho đội frontend:

  • Giữ MSW trong repo frontend để test component.
  • Dùng mock được lưu trữ cho mobile, QA, demo và tích hợp đa nhóm.
  • Khi OpenAPI schema thay đổi, cập nhật mock server để các đội cùng dùng contract mới.
  • Chỉ viết handler MSW cho các case test cụ thể, không cố duy trì toàn bộ API giả lập trong frontend repo.

Bạn có thể tải Apidog để thử song song với setup MSW hiện có.

Các lựa chọn thay thế MSW đáng biết

MSW không phải lựa chọn duy nhất. Tùy stack và mục tiêu, bạn có thể cân nhắc:

  • Mockoon: ứng dụng desktop để tạo mock server local nhanh bằng GUI.
  • WireMock: mock server dựa trên Java, phù hợp với đội JVM và contract testing.
  • Prism của Stoplight: tạo mock trực tiếp từ file OpenAPI qua CLI.
  • json-server: biến file JSON thành REST API nhanh để prototype.

Gợi ý chọn công cụ:

Nhu cầu Công cụ phù hợp
Test component React/Vue trong JS MSW
Mock local nhanh bằng giao diện Mockoon
Mock từ OpenAPI qua CLI Prism
Mock server mạnh cho JVM/backend WireMock
Prototype REST API từ JSON json-server
Mock chia sẻ cho frontend, mobile, QA Hosted mock API như Apidog

Nếu vấn đề chính là “MSW không dùng được cho đồng đội không viết JavaScript”, hãy chọn một mock server dựa trên HTTP. Để xem thêm góc nhìn frontend, đọc bài về cách tạo mock API trong React với Axios.

Câu hỏi thường gặp

MSW có miễn phí không?

Có. Mock Service Worker là mã nguồn mở theo giấy phép MIT và miễn phí dùng trong cả dự án thương mại lẫn phi thương mại.

Bạn chỉ cần cân nhắc chi phí khi chuyển sang mock server được lưu trữ cho nhu cầu chia sẻ toàn đội. Các công cụ như Apidog cũng có gói miễn phí cho trường hợp này.

Apidog có thể thay thế MSW trong unit test không?

Không nên.

MSW chặn request bên trong JavaScript test runner như Jest hoặc Vitest. Apidog là nền tảng được lưu trữ, không phải thư viện import vào test file.

Cách dùng hợp lý:

  • MSW: unit test, component test, local frontend test.
  • Apidog: mock chia sẻ, mock từ schema, mock cho mobile/QA/backend/client không phải JS.

Nếu bạn chỉ tập trung vào test runner, xem thêm hướng dẫn về cách tạo mock lệnh gọi API.

MSW hoạt động trong Node hay chỉ trong trình duyệt?

Cả hai.

  • Trong trình duyệt, MSW dùng Service Worker.
  • Trong Node, MSW vá lớp request để handler chạy trong Jest, Vitest hoặc môi trường test Node.

Đây là một trong những lý do MSW rất phù hợp với đội JavaScript full-stack.

Khi nào nên bổ sung mock server được lưu trữ?

Hãy bổ sung mock server được lưu trữ khi có ít nhất một trong các dấu hiệu sau:

  • mobile app hoặc backend test không dùng JavaScript cần gọi mock
  • QA hoặc designer cần một URL ổn định
  • nhiều đội cần cùng một mock endpoint
  • API được thiết kế bằng OpenAPI trước khi backend hoàn thiện
  • bạn muốn mock sinh tự động từ schema thay vì viết tay toàn bộ handler

Kết luận

MSW rất mạnh cho đúng phạm vi của nó: chặn request trong JavaScript để phục vụ frontend test, unit test và local development. Nó đơn giản, miễn phí, nằm trong repo và rất dễ tích hợp với Jest/Vitest.

Nhưng MSW không được thiết kế để trở thành mock server dùng chung, không phụ thuộc ngôn ngữ, có URL ổn định và sinh từ schema.

Cách tiếp cận thực tế là dùng cả hai:

  • MSW cho test trong frontend repository.
  • Apidog cho mock API được lưu trữ, chia sẻ, dựa trên schema và có thể gọi từ mọi HTTP client.

Nếu mock của bạn đã vượt ra khỏi phạm vi test runner, hãy trỏ frontend, mobile hoặc QA environment đến một mock server dùng chung để giảm phụ thuộc vào backend và giữ contract API nhất quán.

Top comments (0)