You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 11:03:23