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

Node+TypeScript环境下Jest数据库Mock被忽略问题求助

问题:Jest Mock数据库模块失效,断言提示目标非mock函数

问题重现

在Node+TypeScript环境中尝试Mock数据库模块,但运行测试时收到错误:Matcher error: received value must be a mock or spy function,说明Mock未生效,实际调用的是原模块的函数而非mock函数。

测试代码:

import { jest } from '@jest/globals';

jest.mock('../database', () => ({
  insert: jest.fn().mockReturnThis(),
}));

import database from '../database';

describe('create', () => {
  test('creates an enquiry if valid', () => {
    database.insert({ email: 'email@test.com' });
    expect(database.insert).toHaveBeenCalledWith({
      email: 'email@test.com',
    });
  });
});

Jest配置:

/** @type {import('ts-jest').JestConfigWithTsJest} **/
export default {
  testEnvironment: 'node',
  transform: {
    '^.+\\.tsx?$': [
      'ts-jest',
      {
        useESM: true,
      },
    ],
  },
  extensionsToTreatAsEsm: ['.ts', '.tsx'],
};

原因分析及修复方案

1. 适配ESM模块的Mock写法

你的配置启用了ESM模式(useESM: true),而ESM模块的默认导出在Jest的Mock逻辑中需要特殊处理。如果原../database是默认导出,需要在Mock工厂函数中添加__esModule: true标识,并将Mock对象放在default属性下:

import { jest } from '@jest/globals';

jest.mock('../database', () => ({
  __esModule: true, // 标记为ES模块,确保Jest正确解析导出结构
  default: {
    insert: jest.fn().mockReturnThis(),
  },
}));

import database from '../database';

2. 匹配原模块的导出结构

如果原database模块是具名导出(比如export const insert = () => {}),则需要调整Mock结构与原模块一致:

jest.mock('../database', () => ({
  __esModule: true,
  insert: jest.fn().mockReturnThis(),
}));

确保Mock的属性名、导出方式完全匹配原模块,否则Jest无法正确替换原模块的导出内容。

3. 优化ESM模块解析配置

在jest.config.js中添加moduleNameMapper,处理ESM导入时的路径后缀问题:

export default {
  testEnvironment: 'node',
  transform: {
    '^.+\\.tsx?$': [
      'ts-jest',
      {
        useESM: true,
      },
    ],
  },
  extensionsToTreatAsEsm: ['.ts', '.tsx'],
  moduleNameMapper: {
    '^(\\.{1,2}/.*)\\.js$': '$1', // 自动去除导入路径中的.js后缀,适配TypeScript写法
  },
};

4. 验证Mock是否生效

在测试中临时打印database对象,确认Mock是否被正确应用:

test('creates an enquiry if valid', () => {
  console.log(database); // 查看输出是否包含jest.fn()类型的insert函数
  database.insert({ email: 'email@test.com' });
  expect(database.insert).toHaveBeenCalledWith({
    email: 'email@test.com',
  });
});

如果输出中insert不是mock函数,说明Mock的结构或模块路径存在问题,需要重新核对原模块的导出方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 05:58:25