React Testing Library测试点击按钮调用API后子组件的渲染
问题原因
你遇到的问题核心是mock规则配置时机晚于接口调用时机。点击按钮后接口会立即发起请求,此时你还没有配置mock规则,请求直接报错返回undefined,所以状态永远不会更新,页面会一直停留在Loading状态。
修复方案
把mock请求的配置移到点击按钮(最好是组件渲染)之前,同时补充异步交互的await等待,修改后的测试代码如下:
import { render, screen } from "@testing-library/react" import ParentComponent from "../ParentComponent" import userEvent from "@testing-library/user-event" import axios from "axios" import MockAdapter from "axios-mock-adapter" describe("test", () => { let mock beforeAll(() => { mock = new MockAdapter(axios) }) afterEach(() => { mock.reset() }) test("Render child component after api call", async () => { // 先配置mock规则,再执行交互 mock.onGet(`https://pokeapi.co/api/v2/pokemon/ditto`).reply(200, { name: "ditto", id: 132, weight: 40 }) render(<ParentComponent />) const heading = screen.getByText("Display Pokemon Detail") expect(heading).toBeInTheDocument() const toggleButton = screen.getByRole("button", { name: /display/i }) expect(toggleButton).toBeInTheDocument() // userEvent交互是异步方法,必须加await保证交互执行完成 await userEvent.click(toggleButton) const loadingText = await screen.findByText(new RegExp("Loading", "i")) expect(loadingText).toBeInTheDocument() const childHeading = await screen.findByText("ChildComponent") expect(childHeading).toBeInTheDocument() const id = await screen.findByTestId("testId") expect(id).toHaveTextContent("132") }) })
补充说明
- axios-mock-adapter 不会处理配置规则之前已经发起的请求,所有接口的mock配置必须提前完成
- 排查请求问题时,可以打印
mock.history.get查看实际发起的请求地址、参数是否和你的mock规则匹配 - 可选优化:原有代码如果接口请求失败,会一直停留在Loading状态,建议补充错误分支的状态更新:
const retrieveDisplayStatus = async () => { const getPokemonDetailResult = await getPokemonDetail(pokemonName) // 不管接口返回是否成功,都把loading设为false,避免永久卡在加载状态 setPokemonDetail({ detail: getPokemonDetailResult, loading: false, }) }
内容的提问来源于stack exchange,提问作者Moon
相关产品推荐
相关产品推荐

