Jest单元测试:为NextSeo组件Mock并断言传入Props
Hey there, I see you're trying to mock NextSeo to verify the props your Meta component passes to it—great approach! The issue with your current mock is that it's just returning a static string, so it can't capture or reflect the dynamic props being passed. Let's fix that by creating a mock that tracks the props it receives, so you can run proper assertions.
Step 1: Update the NextSeo Mock
Instead of returning a static <div>, we'll turn NextSeo into a Jest mock function. This lets us track every time it's rendered and the exact props it was given. Here's how to adjust your mock:
jest.mock('next-seo', () => ({ NextSeo: jest.fn(() => null), // Mock returns null since we don't need to render actual UI })); // Import the mocked NextSeo to use in our test assertions import { NextSeo } from 'next-seo';
Step 2: Write Targeted Prop Assertions
Now when your Meta component renders NextSeo, the mock function will record the props it received. You can use Jest's toHaveBeenCalledWith to verify those props match your expectations. Let's update your test cases to cover both scenarios (custom values and homepage defaults):
import { shallow } from 'enzyme'; import Meta from './Meta'; // Import your custom Meta component import { NextSeo } from 'next-seo'; import { appMeta } from './path-to-your-appMeta-file'; // Import your appMeta config describe('<Meta/>', () => { beforeEach(() => { // Clear mock calls before each test to avoid cross-test contamination NextSeo.mockClear(); }); it('passes custom title and description to NextSeo when not on homepage', () => { const testTitle = 'title'; const testDescription = 'description'; shallow(<Meta title={testTitle} description={testDescription} />); // Assert NextSeo was called with the exact custom props expect(NextSeo).toHaveBeenCalledWith( { title: testTitle, description: testDescription, }, expect.anything() // Enzyme passes a context argument, we can safely ignore this ); }); it('uses appMeta values when title is set to "Homepage"', () => { // The description prop here should be ignored by the Meta component shallow(<Meta title="Homepage" description="unused description" />); // Assert NextSeo received the appMeta defaults instead expect(NextSeo).toHaveBeenCalledWith( { title: appMeta.title, description: appMeta.description, }, expect.anything() ); }); });
Why This Works
- The
jest.fn()mock captures every invocation ofNextSeo, including the full set of props it was passed. mockClear()in thebeforeEachhook ensures each test starts fresh, with no leftover call data from previous tests.toHaveBeenCalledWithlets you directly validate the props, which is far more reliable than checking rendered HTML strings (we don't need to render actual UI for this test—we just care about the prop flow).
Alternative: Render Props for Debugging (Optional)
If you really want to see the props in a rendered string (like your initial idea), you can adjust the mock to return a component that uses the props:
jest.mock('next-seo', () => ({ NextSeo: (props) => `<div>${props.title} ${props.description}</div>`, }));
Note that with this approach, you'd need to render the mock component and check its output (using html() or text() in Enzyme). However, tracking mock function calls is generally cleaner for prop assertion tests.
内容的提问来源于stack exchange,提问作者James

