React MSW 模拟失效:实际API被调用,测试失败求助
问题:MSW未成功模拟API请求,测试调用了真实接口
组件代码(App.js)
import React, { useState, useEffect } from "react"; const App = () => { const [users, setUsers] = useState(null); const [error, setError] = useState(null); useEffect(() => { const fetchAllUsers = async () => { try { const response = await fetch( "https://jsonplaceholder.typicode.com/users" ); const data = await response.json(); setUsers(data); } catch (err) { setError("Something went wrong!"); } }; fetchAllUsers(); }, []); return ( <> <h1>List of Users</h1> {error && <div>{error}</div>} {users ? ( <ul> {users.map((user) => ( <li key={user.id}>{user.name}</li> ))} </ul> ) : ( <p>No users found</p> )} </> ); }; export default App;
测试代码(App.test.js)
import { render, screen } from "@testing-library/react"; import { rest } from "msw"; import { setupServer } from "msw/node"; import App from "./App"; const server = setupServer( rest.get("https://jsonplaceholder.typicode.com/users", (req, res, ctx) => { res(ctx.json(["Hello World"])); }) ); beforeAll(() => { server.listen(); }); afterAll(() => { server.close(); }); test("empty", async () => { render(<App />); expect(screen.getByText("List of Users")).toBeInTheDocument(); await screen.findByText("Hello world"); });
测试失败信息
Unable to find an element with the text: Hello world. This could be because the text is broken up by multiple elements. In this case, you can provide a function for your text matcher to make your matcher more flexible. Ignored nodes: comments, script, style <body> <div> <h1> List of Users </h1> <ul> <li> Leanne Graham </li> /*skipping a few lines of HTML*/ <li> Clementina DuBuque </li> </ul> </div> </body>
排查与解决方法
1. 修正模拟数据结构与文本匹配
组件渲染的是用户对象的name字段,但当前测试模拟返回的是字符串数组["Hello World"],即使拦截成功,user.name会是undefined,页面不会显示期望文本。同时测试中查找的Hello world与模拟返回的Hello World大小写不一致,也会导致查找失败。
修改MSW的响应数据为符合组件期望的结构:
rest.get("https://jsonplaceholder.typicode.com/users", (req, res, ctx) => { res(ctx.json([{ id: 1, name: "Hello World" }])); });
同时将测试中的查找文本改为Hello World(保持大小写一致)。
2. 确保MSW正确拦截请求
- 检查
msw依赖是否安装完整,执行npm install msw --save-dev确认安装。 - 添加
afterEach钩子重置MSW的请求处理器,避免测试间状态污染:
afterEach(() => { server.resetHandlers(); });
- 可在
beforeAll和afterAll中添加日志,确认MSW服务是否正常启动/关闭,排查初始化失败的可能。
3. 排除其他请求拦截库冲突
如果项目中使用了nock等其他请求拦截工具,可能会与MSW冲突,暂时禁用这类工具后重新测试。
修正后的完整测试代码
import { render, screen } from "@testing-library/react"; import { rest } from "msw"; import { setupServer } from "msw/node"; import App from "./App"; const server = setupServer( rest.get("https://jsonplaceholder.typicode.com/users", (req, res, ctx) => { res(ctx.json([{ id: 1, name: "Hello World" }])); }) ); beforeAll(() => { server.listen(); }); afterEach(() => { server.resetHandlers(); }); afterAll(() => { server.close(); }); test("displays mock user data", async () => { render(<App />); expect(screen.getByText("List of Users")).toBeInTheDocument(); const mockUser = await screen.findByText("Hello World"); expect(mockUser).toBeInTheDocument(); });
内容的提问来源于stack exchange,提问作者Gautham Muralidharan
相关产品推荐
相关产品推荐

