Jest 安装与配置 #

安装 Jest #

基本安装 #

bash
# 使用 npm
npm install --save-dev jest

# 使用 yarn
yarn add --dev jest

# 使用 pnpm
pnpm add --save-dev jest

安装特定版本 #

bash
# 安装特定版本
npm install --save-dev jest@29.7.0

# 安装最新版本
npm install --save-dev jest@latest

全局安装 #

bash
# 全局安装(不推荐)
npm install --global jest

# 推荐使用 npx 运行
npx jest

快速开始 #

创建第一个测试 #

javascript
// sum.js
function sum(a, b) {
  return a + b;
}

module.exports = sum;

// sum.test.js
const sum = require('./sum');

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

运行测试 #

bash
# 运行测试
npx jest

# 运行特定文件
npx jest sum.test.js

# 监听模式
npx jest --watch

添加 npm 脚本 #

json
// package.json
{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
  }
}

配置 Jest #

配置文件 #

Jest 支持多种配置方式:

1. package.json #

json
{
  "jest": {
    "testEnvironment": "jsdom",
    "collectCoverage": true,
    "coverageDirectory": "coverage"
  }
}

2. jest.config.js #

javascript
// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  collectCoverage: true,
  coverageDirectory: 'coverage',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

3. jest.config.ts #

typescript
// jest.config.ts
import type { Config } from 'jest';

const config: Config = {
  testEnvironment: 'jsdom',
  collectCoverage: true,
  coverageDirectory: 'coverage',
};

export default config;

4. 使用 --config 参数 #

bash
jest --config ./config/jest.config.js

常用配置选项 #

javascript
module.exports = {
  // 测试环境
  testEnvironment: 'jsdom', // 或 'node'

  // 根目录
  rootDir: './src',

  // 测试匹配模式
  testMatch: [
    '**/__tests__/**/*.js',
    '**/*.test.js',
    '**/*.spec.js',
  ],

  // 忽略模式
  testPathIgnorePatterns: [
    '/node_modules/',
    '/dist/',
  ],

  // 模块路径映射
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
  },

  // 覆盖率配置
  collectCoverage: true,
  coverageDirectory: 'coverage',
  collectCoverageFrom: [
    'src/**/*.{js,jsx}',
    '!src/**/*.d.ts',
    '!src/index.js',
  ],

  // 设置文件
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],

  // 转换配置
  transform: {
    '^.+\\.js$': 'babel-jest',
  },

  // 模块文件扩展名
  moduleFileExtensions: ['js', 'json', 'jsx'],

  // 全局变量
  globals: {
    'ts-jest': {
      isolatedModules: true,
    },
  },
};

TypeScript 支持 #

安装依赖 #

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

配置 ts-jest #

javascript
// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
  },
};

TypeScript 配置 #

json
// tsconfig.json
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "commonjs",
    "esModuleInterop": true,
    "strict": true,
    "skipLibCheck": true,
    "types": ["jest", "node"]
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

TypeScript 测试示例 #

typescript
// math.ts
export function add(a: number, b: number): number {
  return a + b;
}

// math.test.ts
import { add } from './math';

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

Babel 配置 #

安装 Babel #

bash
npm install --save-dev babel-jest @babel/core @babel/preset-env

Babel 配置 #

javascript
// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', { targets: { node: 'current' } }],
    '@babel/preset-typescript',
    '@babel/preset-react',
  ],
};

使用 Babel 的 Jest 配置 #

javascript
// jest.config.js
module.exports = {
  testEnvironment: 'jsdom',
  transform: {
    '^.+\\.(js|jsx|ts|tsx)$': 'babel-jest',
  },
};

测试环境 #

Node 环境 #

默认环境,适用于 Node.js 项目:

javascript
module.exports = {
  testEnvironment: 'node',
};

jsdom 环境 #

模拟浏览器环境,适用于前端项目:

bash
npm install --save-dev jest-environment-jsdom
javascript
module.exports = {
  testEnvironment: 'jsdom',
};

按文件指定环境 #

javascript
/**
 * @jest-environment jsdom
 */

test('use jsdom in this test file', () => {
  const element = document.createElement('div');
  expect(element).not.toBeNull();
});
javascript
/**
 * @jest-environment node
 */

test('use node in this test file', () => {
  expect(typeof window).toBe('undefined');
});

设置文件 #

setupFilesAfterEnv #

在每个测试文件之前运行的设置文件:

javascript
// jest.config.js
module.exports = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
};
javascript
// jest.setup.js
import '@testing-library/jest-dom';

// 全局设置
beforeAll(() => {
  console.log('Tests starting...');
});

// 自定义匹配器
expect.extend({
  toBeWithinRange(received, floor, ceiling) {
    const pass = received >= floor && received <= ceiling;
    return {
      pass,
      message: () =>
        `expected ${received} ${pass ? 'not ' : ''}to be within range ${floor} - ${ceiling}`,
    };
  },
});

setupFiles #

在测试环境安装之前运行的文件:

javascript
// jest.config.js
module.exports = {
  setupFiles: ['<rootDir>/jest.env.js'],
};
javascript
// jest.env.js
// 设置环境变量
process.env.NODE_ENV = 'test';

// 设置全局变量
global.MY_GLOBAL = 'test value';

模块路径映射 #

简单映射 #

javascript
module.exports = {
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^@components/(.*)$': '<rootDir>/src/components/$1',
    '^@utils/(.*)$': '<rootDir>/src/utils/$1',
  },
};

静态资源映射 #

bash
npm install --save-dev identity-obj-proxy
javascript
module.exports = {
  moduleNameMapper: {
    '\\.(css|less|scss|sass)$': 'identity-obj-proxy',
    '\\.(jpg|jpeg|png|gif|svg)$': '<rootDir>/__mocks__/fileMock.js',
  },
};
javascript
// __mocks__/fileMock.js
module.exports = 'test-file-stub';

预设配置 #

create-react-app #

bash
# 安装
npm install --save-dev react-scripts

# 运行测试
npm test

Next.js #

bash
npm install --save-dev @testing-library/react @testing-library/jest-dom jest-environment-jsdom
javascript
// jest.config.js
const nextJest = require('next/jest');

const createJestConfig = nextJest({
  dir: './',
});

const customJestConfig = {
  setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
  testEnvironment: 'jest-environment-jsdom',
};

module.exports = createJestConfig(customJestConfig);

Vue #

bash
npm install --save-dev @vue/test-utils vue-jest @vue/vue3-jest
javascript
// jest.config.js
module.exports = {
  preset: '@vue/cli-plugin-unit-jest',
  transform: {
    '^.+\\.vue$': '@vue/vue3-jest',
  },
};

命令行选项 #

常用命令 #

bash
# 运行所有测试
jest

# 运行特定文件
jest sum.test.js

# 运行匹配模式的测试
jest --testNamePattern="add"

# 监听模式
jest --watch

# 监听所有文件
jest --watchAll

# 生成覆盖率
jest --coverage

# 更新快照
jest --updateSnapshot

# 并行运行
jest --maxWorkers=4

# 串行运行
jest --runInBand

# 只运行修改的文件
jest --onlyChanged

# 清除缓存
jest --clearCache

# 显示详细输出
jest --verbose

# 静默模式
jest --silent

组合使用 #

bash
# 监听模式 + 覆盖率
jest --watch --coverage

# 运行特定文件 + 更新快照
jest Button.test.js --updateSnapshot

# 并行运行 + 详细输出
jest --maxWorkers=4 --verbose

项目结构 #

推荐结构 #

text
my-project/
├── src/
│   ├── components/
│   │   ├── Button.js
│   │   └── Button.test.js
│   ├── utils/
│   │   ├── math.js
│   │   └── math.test.js
│   └── index.js
├── __tests__/
│   └── integration/
│       └── api.test.js
├── __mocks__/
│   └── axios.js
├── jest.config.js
├── jest.setup.js
└── package.json

测试文件命名 #

text
# Jest 自动识别的测试文件
*.test.js
*.spec.js
__tests__/*.js

调试配置 #

VS Code 配置 #

json
// .vscode/launch.json
{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Jest Debug",
      "program": "${workspaceFolder}/node_modules/.bin/jest",
      "args": ["--runInBand", "--no-cache"],
      "console": "integratedTerminal",
      "internalConsoleOptions": "neverOpen"
    }
  ]
}

调试单个测试 #

bash
# 使用 node 调试
node --inspect-brk node_modules/.bin/jest --runInBand

# 使用 Chrome DevTools
node --inspect-brk node_modules/.bin/jest --runInBand --no-cache

常见问题 #

模块导入问题 #

javascript
// 问题:Cannot find module
// 解决方案:检查 moduleNameMapper 配置
moduleNameMapper: {
  '^@/(.*)$': '<rootDir>/src/$1',
}

TypeScript 类型问题 #

typescript
// 问题:Cannot find name 'test'
// 解决方案:安装 @types/jest
npm install --save-dev @types/jest

CSS 模块问题 #

javascript
// 问题:CSS modules not working
// 解决方案:使用 identity-obj-proxy
moduleNameMapper: {
  '\\.module\\.css$': 'identity-obj-proxy',
}

下一步 #

现在你已经完成了 Jest 的安装和配置,接下来学习 基础测试 开始编写测试!

最后更新:2026-03-28