使用Jest & Enzyme测试NotFound页面的问题求助
Let's break down why your current test isn't working and how to fix it step by step.
First, Identify the Core Issues
- Incorrect
MemoryRouterImport: In React Router v6,MemoryRouterlives inreact-router-dom, notreact-router. Your test imports it from the wrong package, which might break the context yourRoutescomponent needs to access the current location. - Lazy-Loaded Components: Your routes use dynamic
import()calls, meaning theNotFoundPageloads asynchronously. Enzyme'smountdoesn't automatically wait for these async imports to resolve, so your assertion runs before the component finishes rendering. - Potential Route Context Mismatch: If your custom
Routescomponent doesn't properly consume React Router's context (e.g., it manually parseswindow.locationinstead of usinguseLocation), wrapping it inMemoryRouterwon't have any effect.
Fix 1: Correct Import & Handle Async Loading
First, fix the MemoryRouter import, then add logic to wait for the lazy-loaded component to load. Here's how to adjust your Enzyme test:
import React from "react"; import { mount } from "enzyme"; // Import from react-router-dom instead of react-router import { MemoryRouter } from "react-router-dom"; import NotFoundPage from "../routes/not-found/NotFound"; import Routes from "../routes/index"; // Mock the lazy-loaded NotFound component to speed up tests (optional but recommended) jest.mock("../routes/not-found/NotFound", () => () => <div data-testid="not-found">NotFound</div>); describe("NotFoundPage Tests", () => { it("renders NotFoundPage for invalid URLs", async () => { const wrapper = mount( <MemoryRouter initialEntries={["/random"]}> <Routes /> </MemoryRouter> ); // Wait for the async import to resolve and update the component await new Promise(resolve => setImmediate(resolve)); wrapper.update(); // Assert the component exists expect(wrapper.find(NotFoundPage)).toHaveLength(1); // Or use the test ID for more reliable assertions expect(wrapper.find('[data-testid="not-found"]')).toBeTruthy(); }); });
Fix 2: Use React Testing Library (Recommended)
React Testing Library is better suited for handling async components and user-centric testing. Here's a cleaner version of the test:
import React from "react"; import { render, screen, waitFor } from "@testing-library/react"; import { MemoryRouter } from "react-router-dom"; import Routes from "../routes/index"; describe("NotFoundPage Tests", () => { it("displays NotFoundPage for invalid routes", async () => { render( <MemoryRouter initialEntries={["/random"]}> <Routes /> </MemoryRouter> ); // Wait for the NotFound content to appear in the DOM await waitFor(() => { expect(screen.getByText("NotFound")).toBeInTheDocument(); // Replace "NotFound" with actual text from your NotFoundPage }); }); });
Fix 3: If Your Routes Don't Use React Router Context
If your custom Routes component doesn't rely on React Router's context (e.g., it uses manual location parsing), skip the MemoryRouter and directly pass a location prop to your Routes component:
it("renders NotFoundPage for invalid URLs", async () => { const wrapper = mount(<Routes location="/random" />); await new Promise(resolve => setImmediate(resolve)); wrapper.update(); expect(wrapper.find(NotFoundPage)).toHaveLength(1); });
Quick Sanity Check
Double-check your route config to ensure the wildcard (.*) route is the last entry in the children array. Your current config already does this, which is correct—wildcard routes need to be last to avoid overriding valid routes.
内容的提问来源于stack exchange,提问作者alexsouye

