Mocha 是一个 JavaScript 测试框架,上手简单,而且使用起来还比较有趣。 本文旨在通过一些示例来介绍 Mocha 的基础知识,至于各种具体的细节可以参考 Mocha 官网

注意:本文的编程示例均假设你的开发环境为 Ubuntu 系统, 如果你使用 Windows 系统,也可以安装 git bash 以执行 Linux 命令。

目录

  • Mocha 基础用法
    • Mocha 示例
    • 对 Mocha 示例的说明
  • Chai 基础用法
  • 一些常见问题
    • Q1:如何测试异步函数?
    • Q2:如何支持 ES Modules?
    • Q3: 如何只测试部分用例?

Mocha 基础用法

Mocha 示例

下面我们通过一个简单的例子来了解 Mocha 的基础用法。

  1. 在任意路径下创建一个空目录 greetings,并进入此目录。
mkdir greetings
cd greetings
  1. 初始化项目。
npm init -y
  1. 安装 mocha。
npm i -D mocha
  1. package.json 里面的 test 脚本内容修改为 mocha
...,
"scripts": {
  "test": "mocha"
},
...,
  1. 新建一个文件 greetings.js,并在里面添加以下内容:
function hello(name) {
  if (name) {
    return `Hello, ${name}!`
  }

  return 'Error! Please input a valid name.'
}

module.exports = {
  hello,
}
  1. 创建 test 目录。
mkdir test
  1. 在 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!'))
  })
})
  1. 执行 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 接口来举例。

  1. 安装 Chai。
npm i -D chai
  1. 修改第一章中的 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!')
  })
})
  1. 执行 npm test,即可看到测试用例运行结果。

一些常见问题

Q1:如何测试异步函数?

根据 Mocha 官方文档,我们可以使用 async / await 来测试异步函数。以下是一个示例。

  1. 在项目根目录下新建一个文件 lazy_greetings.js,在里面添加以下代码,以实现异步版本的 hello 函数。
function hello(name) {
  return new Promise((resolve) => {
    setTimeout(resolve(`Hello, ${name}!`), 1000)
  })
}

module.exports = {
  hello,
}
  1. 在 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!')
  })
})
  1. 运行 npm test,即可看到测试用例运行结果。你可以尝试把测试用例中的 async / await 去掉,这样测试用例会报错。

Q2:如何支持 ES Modules?

mocha 默认支持 CommonJS Module。要想支持 ES modules,需要稍作改动。

方案一:在 package.json 里面添加一行 "type": "module",

但有时项目代码中不允许这样配置,或者这样配置后会导致编译构建失败,这时可以考虑下面的方案二。

方案二:使用 babel

根据 stack overflow,可以借助 babel 来让 mocha 支持 ES modules。

  1. 安装 @babel/register@babel/preset-env
npm i -D @babel/register @babel/preset-env
  1. 创建 babel 配置文件 babel.config.js,并添加以下内容:
module.exports = {
  presets: [
    '@babel/preset-env'
  ]
}
  1. 修改 package.jsontest 脚本,为 mocha 命令添加 -r 参数:
...,
"script": {
  "test": "mocha -r @babel/register"
}
...,

Q3: 如何只测试部分用例?

根据 stack overflow,可以使用 mocha 的 --grep 选项。

这个选项过滤的是 describe 或 it 语句第一个参数的内容。