使用MSW在Vitest中编写Mock时,无法触发Handler的REST API调用
Vitest中MSW Mock Handler未触发的问题
我在Vitest中为页面渲染时的API调用编写MSW Mock响应,但Handler里的REST API逻辑未触发。调试显示请求已被拦截(日志输出Request intercepted: GET http://x.x.x.x:XXXX/api/job/print/?in_progress=false Request intercepted: GET http://x.x.x.x:XXXX/api/job/print/?in_progress=true),但Handler内的"IM CALLED"日志未出现,且已确认前端确实发起了对应请求。
相关代码如下:
handler.js
import { http } from "msw"; export const handler = [ http.get("*/api/job/print/", (req, res, ctx) => { // const page = req.url.searchParams.get("page"); const in_progress = req.url.searchParams.get("in_progress"); // const expand = req.url.searchParams.get("expand"); console.log("IM CALLED"); // console.log(req.url); if (in_progress === "true") { return res( ctx.status(200), ctx.json({ count: 1, next: null, previous: null, results: [/*some data*/] ) } ]
testcase.test.jsx
import { render, screen, waitFor } from "@testing-library/react"; import { beforeAll, describe, it } from "vitest"; import { MemoryRouter } from "react-router-dom"; import PrintingPage from "../../../../pages/JobPage"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { server } from "./mocks/APIServer"; describe("Jobs hook", () => { const client = new QueryClient(); beforeAll(() => { server.events.on("request:start", ({ request }) => { console.log("Request intercepted:", request.method, request.url); }); }); it("should return a list of print Jobs", async () => { //rendering PrintingPage will call "/api/job/print/" rest API render( <QueryClientProvider client={client}> <MemoryRouter> <PrintingPage /> </MemoryRouter> </QueryClientProvider> ); await waitFor(() => { screen.debug(); // expect(screen.getByText("Retrieving data...")).not.toBeInTheDocument(); }); }); });
APIServer.js
import { setupServer } from "msw/node"; import { handler as JobsHandler } from "./JobsHandler"; export const server = setupServer(...JobsHandler);
vitest.setup.js
import "@testing-library/jest-dom"; import { server } from "./src/features/job/hooks/__tests__/mocks/APIServer"; import { beforeAll, afterEach, afterAll } from "vitest"; beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close());
问题分析与修复方案
1. 路径匹配规则错误
MSW的字符串路径不支持*通配符,你需要改用正则表达式来匹配任意域名下的目标路径:
// 替换原路径字符串为正则表达式 http.get(/^.*\/api\/job\/print\/$/, (req, res, ctx) => { ... })
2. Handler语法与逻辑缺陷
原代码存在两处问题:
ctx.json()的括号未闭合,导致语法错误- 未处理
in_progress === "false"的分支,也没有默认返回值,会导致Handler执行异常
修复后的Handler代码:
import { http } from "msw"; export const handler = [ http.get(/^.*\/api\/job\/print\/$/, (req, res, ctx) => { const in_progress = req.url.searchParams.get("in_progress"); console.log("IM CALLED"); if (in_progress === "true") { return res( ctx.status(200), ctx.json({ count: 1, next: null, previous: null, results: [/* 测试数据 */] }) // 修复:闭合ctx.json括号 ); } // 处理in_progress为false的情况或默认返回 return res( ctx.status(200), ctx.json({ count: 0, next: null, previous: null, results: [] }) ); }) ];
3. 优化React Query测试配置
为避免缓存或重试机制干扰测试,给QueryClient添加默认配置:
const client = new QueryClient({ defaultOptions: { queries: { retry: false, refetchOnWindowFocus: false, }, }, });
内容的提问来源于stack exchange,提问作者johnathan chan
相关产品推荐
相关产品推荐

