You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Enzyme/Jest静态方法Mock未执行问题求助

Troubleshooting Jest Mock for Static Service Method in React Component

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.13 09:20:15