Mocha 是一个 JavaScript 测试框架,上手简单,而且使用起来还比较有趣。 本文旨在通过一些示例来介绍 Mocha 的基础知识,至于各种具体的细节可以参考 Mocha 官网。
注意:本文的编程示例均假设你的开发环境为 Ubuntu 系统, 如果你使用 Windows 系统,也可以安装 git bash 以执行 Linux 命令。
目录
- Mocha 基础用法
- Mocha 示例
- 对 Mocha 示例的说明
- Chai 基础用法
- 一些常见问题
- Q1:如何测试异步函数?
- Q2:如何支持 ES Modules?
- Q3: 如何只测试部分用例?
Mocha 基础用法
Mocha 示例
下面我们通过一个简单的例子来了解 Mocha 的基础用法。
- 在任意路径下创建一个空目录 greetings,并进入此目录。
mkdir greetings
cd greetings
- 初始化项目。
npm init -y
- 安装 mocha。
npm i -D mocha
- 将
package.json里面的test脚本内容修改为mocha
...,
"scripts": {
"test": "mocha"
},
...,
- 新建一个文件
greetings.js,并在里面添加以下内容:
function hello(name) {
if (name) {
return `Hello, ${name}!`
}
return 'Error! Please input a valid name.'
}
module.exports = {
hello,
}
- 创建 test 目录。
mkdir test
- 在 test 目录里新建一个文件
greetings_test.js,并在里面添加以下内容:
const assert = require('assert')
const greetings = require('../greetings')
describe('greetings.hello', () => {
it('should return "Hello, world!"', () => {
const result = greetings.hello('world')
assert(result === 'Hello, world!')
})
it('should return error', () => {
const result = greetings.hello()
assert(result.includes('Error!'))
})
})
- 执行
npm test,即可看到测试用例运行结果。
对 Mocha 示例的说明
- 测试用例都要存放在项目根目录下面的 test 目录(注意不能是 tests 目录)。
- 建议每个 describe 语句测试一个函数或者一个类的一个方法,每个 it 语句测试这个函数的一种输入情况。
Chai 基础用法
从以上示例可以发现,写测试用例一般需要使用断言(assertion)来对函数调用结果进行判断。 上面的示例使用的是 Nodejs 自带的断言库,用起来不够灵活方便。为解决这个问题,我们可以使用 Chai 库。
Chai 是一个 JavaScript 断言库,用起来跟写英语句子差不多,特别自然和舒服。不信请看:
foo.should.be.a('string');
foo.should.equal('bar');
foo.should.have.lengthOf(3);
Chai 支持 should / expect / assert 三种接口,我推荐使用 expect,下面也将按照 expect 接口来举例。
- 安装 Chai。
npm i -D chai
- 修改第一章中的
greetings_test.js。如下所示,将断言语句改用 chai 重写。
const chai = require('chai')
const expect = chai.expect
const greetings = require('../greetings')
describe('greetings.Hello', () => {
it('should return "Hello, world!"', () => {
const result = greetings.hello('world')
expect(result).to.equal('Hello, world!')
})
it('should return error', () => {
const result = greetings.hello()
expect(result).to.include('Error!')
})
})
- 执行
npm test,即可看到测试用例运行结果。
一些常见问题
Q1:如何测试异步函数?
根据 Mocha 官方文档,我们可以使用 async / await 来测试异步函数。以下是一个示例。
- 在项目根目录下新建一个文件
lazy_greetings.js,在里面添加以下代码,以实现异步版本的 hello 函数。
function hello(name) {
return new Promise((resolve) => {
setTimeout(resolve(`Hello, ${name}!`), 1000)
})
}
module.exports = {
hello,
}
- 在 test 目录下新建一个文件
lazy_greetings_test.js,在里面添加以下代码,以测试异步版本的 hello 函数。
const chai = require('chai')
const expect = chai.expect
const greetings = require('../lazy_greetings')
describe('greetings.hello', () => {
it('should return "Hello, world!"', async () => {
const result = await greetings.hello('world')
expect(result).to.equal('Hello, world!')
})
})
- 运行
npm test,即可看到测试用例运行结果。你可以尝试把测试用例中的 async / await 去掉,这样测试用例会报错。
Q2:如何支持 ES Modules?
mocha 默认支持 CommonJS Module。要想支持 ES modules,需要稍作改动。
方案一:在 package.json 里面添加一行 "type": "module",
但有时项目代码中不允许这样配置,或者这样配置后会导致编译构建失败,这时可以考虑下面的方案二。
方案二:使用 babel
根据 stack overflow,可以借助 babel 来让 mocha 支持 ES modules。
- 安装
@babel/register和@babel/preset-env
npm i -D @babel/register @babel/preset-env
- 创建 babel 配置文件
babel.config.js,并添加以下内容:
module.exports = {
presets: [
'@babel/preset-env'
]
}
- 修改
package.json的test脚本,为 mocha 命令添加-r参数:
...,
"script": {
"test": "mocha -r @babel/register"
}
...,
Q3: 如何只测试部分用例?
根据 stack overflow,可以使用 mocha 的 --grep 选项。
这个选项过滤的是 describe 或 it 语句第一个参数的内容。