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

使用Jest Mock portable-fetch遇阻:import*方式失效,require正常

Fixing Jest Mock Issues When Switching from require to ES Modules (import) for portable-fetch

I’ve run into this exact scenario before—CommonJS mocks work smoothly, but switching to ES modules can break your mocks because Jest handles the two module systems differently. Let’s break down why this happens and how to fix it.

Why the require Version Worked

When using require, Jest’s jest.setMock can intercept the CommonJS module loading process before your code imports the module. ES modules, however, are statically analyzed at compile time, so jest.setMock doesn’t get a chance to replace the module before your code references it.

Solution 1: Use jest.mock to Mock portable-fetch Directly

This is the most straightforward fix for ES modules. Jest automatically hoists jest.mock calls to the top of your file, ensuring the mock is in place before your imports run.

Here’s how to adjust your test code:

// Import the mock fetch first
import fetch from 'jest-fetch-mock';
// Import your factory module
import factory from './current-weather';

// Mock the portable-fetch module to export our jest-fetch-mock instance
jest.mock('portable-fetch', () => fetch);

describe('current-weather', () => {
  const config = { appid: 'appid' };
  const currentWeather = factory(config);

  // Reset the mock before each test to avoid cross-test pollution
  beforeEach(() => {
    fetch.resetMocks();
  });

  test('currentWeather()', async () => {
    // Set up your mock response
    fetch.mockResolvedValue({
      json: async () => ({
        // Add your mock API response data here
        main: { temp: 20 },
        name: 'Test City'
      })
    });

    // Run the function under test
    const result = await currentWeather();

    // Assert the mock was called correctly
    expect(fetch).toHaveBeenCalledTimes(1);
    expect(fetch).toHaveBeenCalledWith(
      // Match the expected API URL your function uses
      expect.stringContaining(`appid=${config.appid}`)
    );
    // Add more assertions for the result as needed
    expect(result.temp).toBe(20);
  });
});

Solution 2: Ensure Jest is Configured for ES Modules

If you’re still having issues, double-check your Jest configuration to make sure it handles ES modules properly:

  1. Update jest.config.js:

    module.exports = {
      transform: {
        // Use babel-jest to transpile ES modules
        '^.+\\.jsx?$': 'babel-jest',
      },
      moduleFileExtensions: ['js', 'jsx'],
      // If using TypeScript, add 'ts' and 'tsx' to moduleFileExtensions
    };
    
  2. Check Babel Configuration:
    Make sure your Babel setup includes @babel/preset-env to transpile ES modules to CommonJS for Jest. Your .babelrc or babel.config.json should look something like:

    {
      "presets": [
        ["@babel/preset-env", { "targets": { "node": "current" } }]
      ]
    }
    

Solution 3: Use jest.spyOn for Granular Control

If you need to mock only specific exports or restore the original module after tests, use jest.spyOn:

import * as portableFetch from 'portable-fetch';
import factory from './current-weather';
import fetch from 'jest-fetch-mock';

describe('current-weather', () => {
  const config = { appid: 'appid' };
  const currentWeather = factory(config);
  let fetchSpy;

  beforeEach(() => {
    // Spy on the default export of portable-fetch and replace it with our mock
    fetchSpy = jest.spyOn(portableFetch, 'default').mockImplementation(fetch);
    fetch.resetMocks();
  });

  afterEach(() => {
    // Restore the original fetch implementation after each test
    fetchSpy.mockRestore();
  });

  test('currentWeather()', async () => {
    fetch.mockResolvedValue({ json: async () => ({ main: { temp: 25 } }) });
    const result = await currentWeather();
    
    expect(fetchSpy).toHaveBeenCalled();
    expect(result.temp).toBe(25);
  });
});

The key takeaway is that ES modules require Jest to handle mocking at the static analysis stage, so jest.mock (or jest.spyOn) is the right tool instead of jest.setMock.

内容的提问来源于stack exchange,提问作者user2771738

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:27:34