Mocha 配置 #

配置方式概述 #

Mocha 支持多种配置方式:

text
┌─────────────────────────────────────────────────────────────┐
│                    配置优先级(从高到低)                    │
├─────────────────────────────────────────────────────────────┤
│  1. 命令行参数                                              │
│  2. package.json 中的 mocha 配置                            │
│  3. .mocharc.json / .mocharc.js / .mocharc.yml             │
│  4. mocha.opts(已弃用)                                    │
└─────────────────────────────────────────────────────────────┘

命令行参数 #

基本命令 #

bash
# 运行测试
mocha

# 运行指定文件
mocha test/unit.test.js

# 运行指定目录
mocha test/unit/

# 使用通配符
mocha "test/**/*.test.js"

# 递归运行
mocha --recursive test/

常用参数 #

bash
# 指定测试接口风格
mocha --ui bdd          # BDD 风格(默认)
mocha --ui tdd          # TDD 风格
mocha --ui qunit        # QUnit 风格
mocha --ui exports      # Exports 风格

# 指定报告器
mocha --reporter spec   # 规格报告器(默认)
mocha --reporter dot    # 点矩阵
mocha --reporter list   # 列表
mocha --reporter progress # 进度条
mocha --reporter json   # JSON 格式
mocha --reporter html   # HTML 报告

# 超时设置
mocha --timeout 5000    # 设置超时时间(毫秒)
mocha --slow 100        # 设置慢测试阈值

# 并行执行
mocha --parallel        # 启用并行测试
mocha --jobs 4          # 设置并行工作进程数

# 监听模式
mocha --watch           # 监听文件变化
mocha --watch-extensions js,ts

# 其他选项
mocha --grep "pattern"  # 只运行匹配的测试
mocha --invert          # 反转 grep 匹配
mocha --bail            # 第一个失败后停止
mocha --retries 3       # 失败重试次数
mocha --delay           # 延迟根套件

配置文件 #

.mocharc.json #

json
{
  "timeout": 5000,
  "reporter": "spec",
  "ui": "bdd",
  "recursive": true,
  "extension": ["js", "ts"],
  "spec": "test/**/*.test.js",
  "require": ["@babel/register", "ts-node/register"],
  "ignore": ["test/fixtures/**"],
  "file": ["test/setup.js"],
  "slow": 100,
  "retries": 2,
  "parallel": true,
  "jobs": 4
}

.mocharc.js #

javascript
module.exports = {
  timeout: 5000,
  reporter: 'spec',
  ui: 'bdd',
  recursive: true,
  extension: ['js', 'ts'],
  spec: 'test/**/*.test.js',
  require: ['@babel/register', 'ts-node/register'],
  ignore: ['test/fixtures/**'],
  file: ['test/setup.js'],
  slow: 100,
  retries: 2,

  // 条件配置
  ...(process.env.CI && {
    reporter: 'junit',
    reporterOptions: {
      output: 'test-results.xml'
    }
  })
};

.mocharc.yml #

yaml
timeout: 5000
reporter: spec
ui: bdd
recursive: true
extension:
  - js
  - ts
spec: test/**/*.test.js
require:
  - "@babel/register"
  - "ts-node/register"
ignore:
  - test/fixtures/**
file:
  - test/setup.js
slow: 100
retries: 2
parallel: true
jobs: 4

package.json 配置 #

json
{
  "name": "my-project",
  "version": "1.0.0",
  "mocha": {
    "timeout": 5000,
    "reporter": "spec",
    "ui": "bdd",
    "recursive": true,
    "spec": "test/**/*.test.js"
  },
  "scripts": {
    "test": "mocha"
  }
}

配置选项详解 #

测试文件匹配 #

javascript
// .mocharc.js
module.exports = {
  // 指定测试文件
  spec: [
    'test/unit/**/*.test.js',
    'test/integration/**/*.test.js'
  ],

  // 文件扩展名
  extension: ['js', 'ts', 'tsx'],

  // 递归搜索
  recursive: true,

  // 忽略文件
  ignore: [
    'test/fixtures/**',
    'test/helpers/**'
  ]
};

预处理文件 #

javascript
// .mocharc.js
module.exports = {
  // 在测试前加载的文件
  require: [
    // Babel 支持
    '@babel/register',

    // TypeScript 支持
    'ts-node/register',

    // 测试环境设置
    './test/setup.js',

    // 忽略样式文件
    'ignore-styles'
  ],

  // 全局设置文件(在所有测试之前执行)
  file: [
    './test/bootstrap.js'
  ]
};

测试环境设置 #

javascript
// test/setup.js
const chai = require('chai');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');

// 全局配置 Chai
chai.use(sinonChai);
chai.config.includeStack = true;

// 全局变量
global.expect = chai.expect;
global.sinon = sinon;

// 或者导出设置函数
module.exports = {
  setup: function() {
    // 设置代码
  }
};

报告器配置 #

内置报告器 #

bash
# spec - 详细规格报告(默认)
mocha --reporter spec

# dot - 点矩阵报告
mocha --reporter dot

# list - 简洁列表
mocha --reporter list

# progress - 进度条
mocha --reporter progress

# json - JSON 格式输出
mocha --reporter json

# json-stream - JSON 流
mocha --reporter json-stream

# tap - TAP 格式
mocha --reporter tap

# markdown - Markdown 格式
mocha --reporter markdown

# min - 最小输出
mocha --reporter min

# doc - HTML 文档
mocha --reporter doc > report.html

# xunit - JUnit XML 格式
mocha --reporter xunit --reporter-options output=test-results.xml

# html - 浏览器 HTML 报告
mocha --reporter html

报告器选项 #

javascript
// .mocharc.js
module.exports = {
  reporter: 'xunit',
  reporterOptions: {
    output: 'test-results.xml',
    suiteName: 'My Test Suite'
  }
};
bash
# 命令行方式
mocha --reporter xunit --reporter-options output=test-results.xml

自定义报告器 #

javascript
// custom-reporter.js
const Mocha = require('mocha');

class CustomReporter extends Mocha.reporters.Base {
  constructor(runner, options) {
    super(runner, options);

    console.log('Custom Reporter Started');

    runner.on('pass', function(test) {
      console.log(`✓ ${test.fullTitle()}`);
    });

    runner.on('fail', function(test, err) {
      console.log(`✗ ${test.fullTitle()}`);
      console.log(err.message);
    });

    runner.on('end', function() {
      console.log(`Total: ${runner.stats.tests}`);
      console.log(`Passed: ${runner.stats.passes}`);
      console.log(`Failed: ${runner.stats.failures}`);
    });
  }
}

module.exports = CustomReporter;
bash
# 使用自定义报告器
mocha --reporter ./custom-reporter.js

并行测试 #

启用并行 #

bash
# 启用并行测试
mocha --parallel

# 设置工作进程数
mocha --parallel --jobs 4
javascript
// .mocharc.js
module.exports = {
  parallel: true,
  jobs: 4
};

并行测试注意事项 #

javascript
// 并行测试中,每个文件在独立进程中运行
// 需要确保测试隔离

describe('Parallel Test', function() {
  // ❌ 避免使用全局状态
  // globalState = {};

  // ✅ 使用 beforeEach 初始化
  let state;

  beforeEach(function() {
    state = {};
  });

  it('test 1', function() {
    state.value = 1;
    // 不会影响其他测试
  });

  it('test 2', function() {
    expect(state.value).to.be.undefined;
  });
});

并行测试配置 #

javascript
// .mocharc.js
module.exports = {
  parallel: true,
  jobs: process.env.CI ? 2 : 4, // CI 环境使用较少进程

  // 并行测试需要文件级别隔离
  file: ['./test/setup.js'],

  // 禁用根钩子(并行中不共享)
  global: []
};

TypeScript 支持 #

配置 ts-node #

bash
npm install --save-dev ts-node typescript
javascript
// .mocharc.js
module.exports = {
  extension: ['ts'],
  spec: 'test/**/*.test.ts',
  require: [
    'ts-node/register',
    './test/setup.ts'
  ]
};

TypeScript 配置 #

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

TypeScript 测试示例 #

typescript
// test/user.test.ts
import { expect } from 'chai';
import { User } from '../src/user';

describe('User', function() {
  let user: User;

  beforeEach(function() {
    user = new User('John', 'john@example.com');
  });

  it('should have correct name', function() {
    expect(user.name).to.equal('John');
  });

  it('should update name', function() {
    user.setName('Jane');
    expect(user.name).to.equal('Jane');
  });
});

Babel 支持 #

配置 Babel #

bash
npm install --save-dev @babel/core @babel/register @babel/preset-env
javascript
// .mocharc.js
module.exports = {
  require: ['@babel/register'],
  spec: 'test/**/*.test.js'
};
javascript
// babel.config.js
module.exports = {
  presets: [
    ['@babel/preset-env', {
      targets: { node: 'current' }
    }]
  ]
};

测试过滤 #

使用 grep #

bash
# 只运行名称包含 "User" 的测试
mocha --grep "User"

# 使用正则表达式
mocha --grep "/User|Product/"

# 反转匹配(运行不匹配的测试)
mocha --grep "slow" --invert

测试文件中过滤 #

javascript
describe('User', function() {
  it('should create user', function() { /* ... */ });
  it('should delete user', function() { /* ... */ });
});

describe('Product', function() {
  it('should create product', function() { /* ... */ });
});

// 只运行 User 相关测试
// mocha --grep "User"

环境变量 #

使用环境变量配置 #

javascript
// .mocharc.js
module.exports = {
  timeout: process.env.TEST_TIMEOUT || 5000,
  reporter: process.env.CI ? 'junit' : 'spec',
  parallel: process.env.CI === 'true',
  jobs: parseInt(process.env.JOBS || '4', 10)
};
bash
# 使用环境变量
TEST_TIMEOUT=10000 mocha
CI=true mocha

CI/CD 配置 #

GitHub Actions #

yaml
# .github/workflows/test.yml
name: Test

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [16, 18, 20]

    steps:
      - uses: actions/checkout@v3

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v3
        with:
          node-version: ${{ matrix.node-version }}

      - run: npm ci

      - name: Run tests
        run: npm test
        env:
          CI: true

      - name: Upload coverage
        uses: codecov/codecov-action@v3

GitLab CI #

yaml
# .gitlab-ci.yml
test:
  image: node:18
  script:
    - npm ci
    - npm test
  artifacts:
    reports:
      junit: test-results.xml
    paths:
      - coverage/

Jenkins #

groovy
// Jenkinsfile
pipeline {
  agent any

  stages {
    stage('Install') {
      steps {
        sh 'npm ci'
      }
    }

    stage('Test') {
      steps {
        sh 'npm test -- --reporter xunit --reporter-options output=test-results.xml'
      }
      post {
        always {
          junit 'test-results.xml'
        }
      }
    }
  }
}

代码覆盖率 #

使用 nyc #

bash
npm install --save-dev nyc
json
// package.json
{
  "scripts": {
    "test": "mocha",
    "test:coverage": "nyc mocha"
  }
}
javascript
// .nycrc.json
{
  "reporter": ["text", "html", "lcov"],
  "exclude": [
    "test/**",
    "node_modules/**"
  ],
  "check-coverage": true,
  "statements": 80,
  "branches": 80,
  "functions": 80,
  "lines": 80
}

最佳实践 #

1. 使用配置文件 #

javascript
// .mocharc.js
module.exports = {
  // 基本配置
  timeout: 5000,
  reporter: 'spec',
  ui: 'bdd',
  recursive: true,

  // 测试文件
  spec: 'test/**/*.test.js',
  extension: ['js'],

  // 预处理
  require: ['./test/setup.js'],

  // CI 环境特殊配置
  ...(process.env.CI && {
    reporter: 'junit',
    reporterOptions: {
      output: 'test-results.xml'
    },
    parallel: true
  })
};

2. 分离测试脚本 #

json
// package.json
{
  "scripts": {
    "test": "mocha",
    "test:unit": "mocha test/unit",
    "test:integration": "mocha test/integration",
    "test:coverage": "nyc mocha",
    "test:watch": "mocha --watch"
  }
}

3. 环境隔离 #

javascript
// test/setup.js
process.env.NODE_ENV = 'test';
process.env.DATABASE_URL = 'postgresql://test:test@localhost:5432/test_db';

const chai = require('chai');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');

chai.use(sinonChai);

global.expect = chai.expect;
global.sinon = sinon;

下一步 #

现在你已经掌握了 Mocha 的配置方法,接下来学习 高级特性 了解更多高级用法!

最后更新:2026-03-28