文章目录

TypeScript 测试:Jest 与 ts-jest 配置

发布于 2026-04-03 04:37:43 · 浏览 7 次 · 评论 0 条

TypeScript 测试:Jest 与 ts-jest 配置

安装 必要的依赖包。在项目根目录下打开终端,执行以下命令:

npm install --save-dev jest typescript ts-jest @types/jest

这会安装 Jest 测试框架、TypeScript 编译器、ts-jest 预处理器(用于在测试中直接运行 .ts 文件),以及 Jest 的类型定义文件。


初始化 Jest 配置文件。运行以下命令让 Jest 自动生成配置:

npx jest --init

系统会交互式提问,按以下推荐选项选择:

  • 是否希望 Jest 在每次运行前清除 mock 和测试状态?选 Yes
  • 要使用哪种测试环境?选 node(如果是 Node.js 项目)或 jsdom(如果是浏览器相关逻辑)。
  • 是否需要收集测试覆盖率?建议选 Yes
  • 是否希望 Jest 自动清理未使用的代码?选 No(可后续手动配置)。

该命令会生成一个 jest.config.js 文件。


修改 jest.config.js 以支持 TypeScript。打开该文件,找到 preset 字段,将其值改为 'ts-jest'。完整配置示例如下:

/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coverageProvider: 'v8',
};

关键点是 preset: 'ts-jest',它告诉 Jest 使用 ts-jest 来处理 TypeScript 文件,无需额外编译步骤。


确保 项目根目录存在有效的 tsconfig.json。如果还没有,请创建一个。最简配置如下:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "outDir": "./dist"
  },
  "include": ["src/**/*", "tests/**/*"]
}

注意 include 字段必须包含你的源码和测试文件路径(例如 srctests),否则 ts-jest 可能无法正确解析类型。


编写 第一个 TypeScript 测试文件。假设你有一个 src/math.ts 文件:

export function add(a: number, b: number): number {
  return a + b;
}

tests/ 目录下创建 math.test.ts

import { add } from '../src/math';

test('adds 1 + 2 to equal 3', () => {
  expect(add(1, 2)).toBe(3);
});

文件扩展名必须是 .test.ts.spec.ts,Jest 才会自动识别为测试文件。


运行 测试验证配置是否生效。在终端执行:

npx jest

如果看到绿色的 PASS 提示和覆盖率报告,说明配置成功。若报错,请检查以下常见问题:

  • 是否遗漏安装 ts-jest@types/jest
  • jest.config.js 中是否设置了 preset: 'ts-jest'
  • tsconfig.jsoninclude 是否覆盖了测试文件所在目录?

调试 类型错误。Jest 本身不检查类型,仅运行测试。要同时检查类型和运行测试,可添加两个脚本到 package.json

{
  "scripts": {
    "test": "jest",
    "type-check": "tsc --noEmit"
  }
}

先运行 npm run type-check 确保无类型错误,再运行 npm run test 执行测试。


配置 模块路径别名(可选)。如果你在 tsconfig.json 中使用了 paths,例如:

{
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@utils/*": ["src/utils/*"]
    }
  }
}

则需在 jest.config.js 中同步映射路径。安装 jest-module-name-mapper

npm install --save-dev jest-module-name-mapper

然后修改配置:

const { pathsToModuleNameMapper } = require('ts-jest');
const { compilerOptions } = require('./tsconfig.json');

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  moduleNameMapper: pathsToModuleNameMapper(compilerOptions.paths, {
    prefix: '<rootDir>/',
  }),
};

这样 Jest 才能正确解析 import { foo } from '@utils/bar' 这类语句。


启用 ES 模块支持(适用于现代项目)。如果你的 package.json 包含 "type": "module",需调整配置:

  1. jest.config.js 改名为 jest.config.mjs
  2. 修改内容为 ESM 语法:
/** @type {import('ts-jest').JestConfigWithTsJest} */
export default {
  preset: 'ts-jest/presets/default-esm',
  testEnvironment: 'node',
  extensionsToTreatAsEsm: ['.ts'],
  globals: {
    'ts-jest': {
      useESM: true,
    },
  },
};

同时确保 tsconfig.jsonmodule 设置为 NodeNextESNext


优化 测试性能。大型项目可启用增量测试和缓存:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  cache: true,
  maxWorkers: '50%',
  testMatch: ['<rootDir>/tests/**/*.test.ts'],
};

maxWorkers: '50%' 限制 CPU 使用,避免机器卡顿;cache: true 加速重复运行。


处理 全局变量或 DOM 环境。若测试涉及浏览器 API(如 windowdocument),将 testEnvironment 改为 'jsdom'

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
};

jsdom 是一个轻量级的 DOM 实现,无需启动真实浏览器即可模拟前端环境。


验证 覆盖率阈值(可选)。在 jest.config.js 中添加:

module.exports = {
  // ...其他配置
  coverageThreshold: {
    global: {
      branches: 80,
      functions: 80,
      lines: 80,
      statements: 80
    }
  }
};

当覆盖率低于 80% 时,测试将失败,强制团队提升测试完整性。


解决 常见报错。若出现 SyntaxError: Cannot use import statement outside a module,通常是因为 Jest 尝试直接运行未编译的 ESM 文件。解决方案:

  • 确保使用 ts-jest 预设(非 babel-jest)。
  • 若项目为 CommonJS,tsconfig.jsonmodule 应设为 commonjs
  • 不要混用 .ts.js 扩展名导入。

组织 测试文件结构。推荐保持测试文件与源码同名并置于 tests/ 目录:

project/
├── src/
│   └── utils/
│       └── math.ts
└── tests/
    └── utils/
        └── math.test.ts

这种镜像结构便于快速定位测试文件,也方便 IDE 自动关联。


运行 单个测试文件。调试时无需跑全量测试,直接指定文件路径:

npx jest tests/utils/math.test.ts

--watch 参数可进入监听模式,文件保存后自动重跑:

npx jest --watch tests/utils/math.test.ts

模拟 外部依赖。使用 Jest 内置的 mock 功能隔离测试单元。例如,若 math.ts 依赖一个网络模块:

// src/api.ts
export const fetchData = async (): Promise<number> => {
  // 实际调用 API
};

// src/math.ts
import { fetchData } from './api';
export const compute = async (): Promise<number> => {
  const data = await fetchData();
  return data * 2;
};

在测试中模拟 fetchData

// tests/math.test.ts
import { compute } from '../src/math';

jest.mock('../src/api', () => ({
  fetchData: jest.fn().mockResolvedValue(10),
}));

test('compute doubles the fetched value', async () => {
  const result = await compute();
  expect(result).toBe(20);
});

jest.mock 会在模块加载前替换实现,确保测试不依赖外部服务。


配置 自定义匹配器(可选)。通过 expect.extend 添加领域专用断言。例如,验证数字是否接近:

// tests/setup.ts
expect.extend({
  toBeCloseTo(received: number, expected: number, precision = 2) {
    const pass = Math.abs(received - expected) < Math.pow(10, -precision);
    return {
      message: () => `expected ${received} to be close to ${expected}`,
      pass,
    };
  },
});

// jest.config.js
module.exports = {
  // ...
  setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
};

之后可在测试中使用 expect(value).toBeCloseTo(3.14)


升级 依赖保持兼容。定期更新 Jest 生态:

npm update jest ts-jest @types/jest

重大版本升级前,查阅 ts-jest 官方迁移指南,避免配置失效。


禁用 类型检查加速测试(仅限 CI 快速反馈)。在持续集成中,有时只需验证逻辑正确性,可跳过类型检查:

npx jest --no-cache --passWithNoTests

但日常开发仍应结合类型检查,避免隐藏错误。


处理 异步测试超时。默认 Jest 等待异步操作 5 秒,超时则失败。延长等待时间:

test('handles slow API', async () => {
  // ...
}, 10000); // 10 秒

或全局设置(在 jest.config.js 中):

module.exports = {
  // ...
  testTimeout: 10000,
};

复用 测试工具函数。将常用辅助逻辑提取到 tests/helpers.ts

// tests/helpers.ts
export const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

在测试中直接导入使用,避免重复代码。


验证 配置最终形态。完整的 jest.config.js 示例:

/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  collectCoverage: true,
  coverageDirectory: 'coverage',
  coverageProvider: 'v8',
  testMatch: ['<rootDir>/tests/**/*.test.ts'],
  setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

此配置覆盖了路径别名、覆盖率、自定义设置等常见需求,可直接用于新项目。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文