Jest配合MSW测试Vue组件时未等待Axios Promise导致测试失败
问题原因和解决方案
你的测试失败是两处写法错误导致,和Jest、MSW本身的Bug无关,按以下步骤修改即可正常运行:
1. 修复MSW Mock的响应内容
你当前的MSW请求处理逻辑只返回了200状态码,没有返回业务需要的响应体,组件中response.data.id拿到的是空值,result_id自然不会被赋值为有效值,v-if始终不触发。
修改请求处理函数,补充和真实接口一致的响应体:
rest.post("https://jsonplaceholder.typicode.com/posts", (req, res, ctx) => { return res( ctx.status(200), ctx.json({ id: 101, title: 'foo 2', body: 'bar 2', userId: 2 }) ) })
2. 修正测试异步逻辑
你在点击按钮后直接关闭了MSW服务,此时Axios请求可能还未完成,同时用了同步的queryBy*方法查询DOM,没有等待请求完成、Vue异步更新DOM的过程。
- 将MSW服务的初始化、启动、关闭抽离到测试生命周期钩子中,避免提前终止服务
- 用
findBy*异步查询方法替代queryBy*,findBy*会自动等待最多1秒直到元素出现,天然适配异步场景
修改后的完整测试代码:
import TestPage from './TestPage.vue'; import { render, screen } from '@testing-library/vue'; import "@testing-library/jest-dom" import userEvent from '@testing-library/user-event'; import { setupServer } from 'msw/node' import { rest } from "msw" // 全局初始化MSW服务 const server = setupServer( rest.post("https://jsonplaceholder.typicode.com/posts", (req, res, ctx) => { return res( ctx.status(200), ctx.json({ id: 101, title: 'foo 2', body: 'bar 2', userId: 2 }) ) }) ); // 管理MSW生命周期 beforeAll(() => server.listen()) afterEach(() => server.resetHandlers()) afterAll(() => server.close()) describe("Test Page", () => { it("Tests axios", async () => { render(TestPage); const button = screen.getByRole("button", { name: "Test Axios" }); await userEvent.click(button); // 异步等待元素渲染 const text = await screen.findByText("RESULT 101"); expect(text).toBeInTheDocument(); }); });
可选优化:让提交方法返回Promise
如果需要更精准的控制等待时机,可以修改组件的submitForm方法,返回Axios请求的Promise:
submitForm() { return axios.post('https://jsonplaceholder.typicode.com/posts',{ title: 'foo 2', body: 'bar 2', userId: 2, }).then( (response) => { this.result_id = response.data.id; } ); }
内容的提问来源于stack exchange,提问作者Liam Arbel
相关产品推荐
相关产品推荐

