Enzyme/Jest静态方法Mock未执行问题求助
Hey there! Let's break down why your mock isn't catching the goToNext call and fix it step by step. I've run into similar issues as a Jest newbie, so I feel your pain!
First, Let's Identify the Key Issues
Your test is failing for a few common Jest/React testing pitfalls:
1. Jest.mock Hoisting Broke Your Mock Reference
In your first mock attempt, you defined goToNextMock after calling jest.mock()—but Jest hoists all jest.mock() calls to the top of the file, regardless of your code order. That means when the mock runs, goToNextMock doesn't exist yet! Your static method ends up calling undefined, so your mock never gets triggered.
2. Module Caching Makes Your Late Mock Irrelevant
In your second test, you tried reassigning Service.goToNext directly, but if you imported your NextButton component before this mock, React already cached the original goToNext reference in the component's onClick handler. Your late mock won't update that existing reference.
3. Your Mock Structure Might Not Match the Real Service
If your actual Services/service module exports an object (not a class with static methods), mocking it as a class will create a mismatch. The component is calling Service.goToNext on an object, but your mock provides a class—they're not the same thing!
Fixes That Work
Fix 1: Correct the Mock Structure & Avoid Hoisting Issues
First, make sure your mock matches how your real Service is exported. Let's assume your Services/service looks like this (the most common pattern):
// Services/service.js export default { goToNext: () => { /* real implementation */ } };
Update your mock to export an object with a direct Jest mock function, and import the service to assert against:
// Import after setting up the mock jest.mock('Services/service', () => ({ default: { goToNext: jest.fn() } })); import React from 'react'; import { shallow } from 'enzyme'; import Service from 'Services/service'; import NextButton from './NextButton'; it('should call goToNext when button is clicked', () => { // Render the component const wrapper = shallow(<NextButton submitting={false} />); // Simulate click wrapper.find('button').simulate('click'); // Assert the mock was called expect(Service.goToNext).toHaveBeenCalled(); });
Fix 2: Use jest.spyOn for Easier Mocking
If you want to temporarily replace the real goToNext implementation (instead of mocking the entire module), jest.spyOn is cleaner and avoids hoisting issues:
import React from 'react'; import { shallow } from 'enzyme'; import Service from 'Services/service'; import NextButton from './NextButton'; it('should call goToNext when button is clicked', () => { // Spy on the static method and replace it with a mock const goToNextSpy = jest.spyOn(Service, 'goToNext').mockImplementation(() => {}); const wrapper = shallow(<NextButton submitting={false} />); wrapper.find('button').simulate('click'); expect(goToNextSpy).toHaveBeenCalled(); // Clean up the spy to restore the original method goToNextSpy.mockRestore(); });
Fix 3: Ensure Components Are Imported After Mocks
If you need to mock dynamically per test case, import your component inside the test (after setting up the mock) to bypass module caching:
import React from 'react'; import { shallow } from 'enzyme'; import Service from 'Services/service'; it('should call goToNext when button is clicked', () => { const mockGoToNext = jest.fn(); // Override the service mock for this test jest.doMock('Services/service', () => ({ default: { goToNext: mockGoToNext } })); // Dynamically import the component NOW that the mock is set up const NextButton = require('./NextButton').default; const wrapper = shallow(<NextButton submitting={false} />); wrapper.find('button').simulate('click'); expect(mockGoToNext).toHaveBeenCalled(); });
Quick Check: Verify Your Component's Service Import
Double-check that your NextButton is importing the service correctly. If it's using a named import instead of default, adjust your mock accordingly:
// If component uses: import { goToNext } from 'Services/service'; jest.mock('Services/service', () => ({ goToNext: jest.fn() })); // Then assert with: import { goToNext } from 'Services/service'; expect(goToNext).toHaveBeenCalled();
内容的提问来源于stack exchange,提问作者aln447

