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