msw TypeScript 完全指南:安装、方法与实战示例
什么是 msw?为什么需要它?
Mock Service Worker (msw) 是一款基于 Service Worker API 的网络请求拦截与模拟库。与传统的解决方案(如 axios-mock-adapter 或 nock)不同,msw 在浏览器或 Node.js 层面拦截真实的 HTTP 请求,并返回预设的响应数据。这意味着你无需启动真实服务器或修改应用代码,即可完成测试。
msw 的核心目标是提供一套统一的 API 模拟工具,既可用于浏览器端测试(借助真实的 Service Worker),也可用于服务端测试(Node.js)。对于使用 TypeScript 的开发者来说,msw 尤为友好,因为它为所有请求和响应提供了严格的类型支持。无论是单元测试、集成测试,还是在前端与后端分离开发时,msw 都是理想的选择。
msw 的最大优势在于:模拟发生在网络层面,而非代码层面。这意味着任何执行 HTTP 请求的库(如 fetch、axios、graphql-request 等)都会被自动拦截,无需额外配置。该库支持 REST API、GraphQL,甚至可以通过扩展处理 WebSocket 连接。
安装 msw
在 TypeScript 项目中安装 msw,请执行以下任一命令:
# npm
npm install msw --save-dev
# yarn
yarn add msw --dev
# pnpm
pnpm add msw --save-dev
安装完成后,如需在浏览器中使用,需初始化 Service Worker:
npx msw init public/ --save
若仅在 Node.js 服务端使用,则无需额外初始化。
快速上手:最小化示例
下面创建一个简单的 REST API 模拟示例,包含处理程序定义、服务器配置和测试请求。
// handlers.ts
import { http, HttpResponse } from 'msw';
export const handlers = [
http.get('https://api.example.com/user', () => {
return HttpResponse.json({
id: 'c7b3d8e0-5e0b-4b0f-8b3a-3b9f4b3d3b3f',
firstName: 'John',
lastName: 'Maverick',
});
}),
];
// server.ts (用于 Node.js)
import { setupServer } from 'msw/node';
import { handlers } from './handlers';
export const server = setupServer(...handlers);
// test.ts
import { server } from './server';
beforeAll(() => server.listen());
afterEach(() => server.resetHandlers());
afterAll(() => server.close());
test('应成功获取用户数据', async () => {
const response = await fetch('https://api.example.com/user');
const data = await response.json();
expect(data.firstName).toBe('John');
});
核心方法与函数
1. http.get()
函数签名: http.get(url: string | RegExp, resolver: (info: HttpRequestInfo) => HttpResponse)
说明: 创建一个 GET 请求的处理程序。支持精确字符串、正则表达式以及带参数的 URL 模板。
import { http, HttpResponse } from 'msw';
export const handler = http.get('https://api.example.com/users/:id', ({ params }) => {
const { id } = params;
return HttpResponse.json({ id, name: '用户 ' + id });
});
2. http.post()
函数签名: http.post(url: string | RegExp, resolver: (info: HttpRequestInfo) => HttpResponse)
说明: 创建一个 POST 请求的处理程序。可通过 request.json() 读取请求体。
import { http, HttpResponse } from 'msw';
export const handler = http.post('https://api.example.com/users', async ({ request }) => {
const body = await request.json();
return HttpResponse.json({ ...body, id: '新用户ID' }, { status: 201 });
});