思路:
- action中发请求
- handlers拦截这个请求,返回数据
msw的使用
- 使用handlers配置匹配规则,MSW 1.0之后可以直接使用封装好的
http
和HttpResponse
,无需使用rest
- 拦截浏览器中的请求应使用
setupWorker
,拦截node环境中的请求应使用setupServer
,所以测试server action使用setupServer - 需要注意,
setupServer
需要一个持久化 Node.js 进程,所以常常使用在单独的测试进程中,比如使用Vitest - 如果想将msw放在本地开发服务器上,为了防止热重载造成状态丢失,需要在根layout文件中的
RootLayout
函数之外直接调用server.listen()
Vitest使用
-
创建测试入口文件
vitest.setup.ts
,写入:javascriptimport { beforeAll, afterEach, afterAll } from 'vitest'; import { server } from './mocks/server'; // 测试前,启动服务端拦截 beforeAll(() => { server.listen({ onUnhandledRequest: 'warn' }); }); // 每个测试结束后,重置处理器(防止测试间互相污染) afterEach(() => { server.resetHandlers(); }); // 所有测试完成后,关闭拦截器 afterAll(() => { server.close(); });
-
创建配置文件
vitest.config.ts
,写入:phpimport { defineConfig } from 'vitest/config'; export default defineConfig({ test: { // 指定刚才写的 setup 文件位置 setupFiles: ['./vitest.setup.ts'], // 如果需要测试环境为 "jsdom"(测试 React 组件)或 "node"(仅测后端逻辑),可在这里配置 environment: 'node', }, });
-
创建
/src/__test__
文件夹,创建测试文件actions.test.ts
(比如我要测试action.ts
),写入:javascript// __tests__/actions.test.ts import { test, expect } from 'vitest'; import { getData } from '@/app/actions'; test('Mock server action fetch', async () => { const data = await getData(); const mockData={ id:1, name:"Hello from MSW" } expect(data).toEqual(mockData); })
-
在
package.json
里添加脚本"test": "vitest"
,运行pnpm test
即可
注意事项:
https://randomuser.me/api/?results=3&inc=name,gender,email,nat,picture&noinfo
返回的数据需要解构出results
使用action.ts
中使用的其他文件中的函数,那个文件必须显式标注成"use server"
才行