MSW chặn request ở tầng network (Service Worker trên browser, interceptor trên Node), nên code ứng dụng không biết mình đang bị mock — không cần sửa fetch hay axios instance.
Setup dùng chung cho cả suite:
ts
// src/test/server.ts
import { setupServer } from "msw/node"
import { http, HttpResponse } from "msw"
export const handlers = [
http.get("/api/users", () => HttpResponse.json([{ id: 1, name: "Dinh" }])),
]
export const server = setupServer(...handlers)
// setup file
beforeAll(() => server.listen({ onUnhandledRequest: "error" }))
afterEach(() => server.resetHandlers()) // undo per-test overrides
afterAll(() => server.close())onUnhandledRequest: "error" rất đáng bật: request nào chưa khai báo handler sẽ làm test fail thay vì lặng lẽ đi ra mạng thật.
Giả lập lỗi cho một test bằng server.use(...) — handler này bị resetHandlers() dọn sau mỗi test nên không rò rỉ:
ts
it("shows an error message when the API fails", async () => {
server.use(http.get("/api/users", () => new HttpResponse(null, { status: 500 })))
render(<UserList />)
expect(await screen.findByText(/something went wrong/i)).toBeInTheDocument()
})
// network failure instead of an HTTP error
server.use(http.get("/api/users", () => HttpResponse.error()))Dùng chung một bộ handler cho unit test, Storybook và dev server giúp dữ liệu giả không bị lệch giữa các môi trường.