使用MSW验证Vue项目中useFetch请求的请求体正确性
解决请求体断言因JSON键顺序不一致失败的问题
核心原因
直接断言JSON.stringify后的字符串会因为对象键的序列化顺序(比如插入顺序、JS引擎差异)导致匹配失败,正确的做法是比较解析后的对象本身,而非序列化后的字符串。
方案1:用MSW直接捕获并断言请求体(推荐)
MSW本身提供了拦截请求并获取请求体的能力,无需手动mock fetch,更贴近真实请求场景:
import { rest } from 'msw' import { setupServer } from 'msw/node' import { postEndpoint } from '@/your-module' // 配置MSW服务器 const server = setupServer( rest.post('/api/your-endpoint', async (req, res, ctx) => { // 解析请求体为对象 const requestBody = await req.json() // 用toEqual做深度相等断言,忽略键顺序 expect(requestBody).toEqual({ keyB: 'valueB', keyA: 'valueA', nested: { foo: 'bar' } }) return res(ctx.status(200)) }) ) // MSW生命周期钩子 beforeAll(() => server.listen()) afterEach(() => server.resetHandlers()) afterAll(() => server.close()) test('postEndpoint发送正确的请求体', async () => { await postEndpoint() })
方案2:如果必须mock fetch,解析请求体后断言
如果你坚持用vi.spyOn mock fetch,不要直接比较序列化字符串,而是解析请求体后做对象断言:
import { postEndpoint } from '@/your-module' test('postEndpoint发送正确的请求体', async () => { const fetchSpy = vi.spyOn(global, 'fetch').mockImplementation(async (url, options) => { if (url === '/api/your-endpoint' && options.method === 'POST') { // 解析请求体 const requestBody = await new Response(options.body).json() // 深度断言对象相等 expect(requestBody).toEqual({ keyB: 'valueB', keyA: 'valueA', nested: { foo: 'bar' } }) } // 返回一个mock响应 return new Response(JSON.stringify({}), { status: 200 }) }) await postEndpoint() fetchSpy.mockRestore() })
关键说明
Vitest的toEqual方法会进行深度值比较,完全忽略对象键的顺序,只校验结构和对应值是否一致,这是解决序列化顺序问题的核心。
内容的提问来源于stack exchange,提问作者Theiaz
相关产品推荐
相关产品推荐

