用Mocha、Chai、Sinon测试Node.js的详细指南

686 阅读5分钟

本教程演示了如何在Node.js中用Mocha、Chai和Sinon设置测试。前面的教程已经向你展示了如何设置你的Node.js应用程序,而本教程为你的Node.js项目设置了一个测试环境。让我们通过设置Mocha与Chai和Sinon作为测试框架来深入了解它。

使用Mocha的Node.js

Mocha将是我们的测试运行器,负责将我们的测试封装在测试套件(describe-block)和测试案例(it-block)中。此外,像Mocha这样的测试运行器提供了一个API,可以从一个命令行界面运行所有的测试。让我们深入了解一下。首先,为你的Node.js应用程序安装一个额外的Babel包,使我们的测试能够理解支持Babel的JavaScript代码:

npm install @babel/register --save-dev

第二,将我们的测试运行器Mocha安装为node包:

npm install mocha --save-dev

第三,在你的package.json中包括一个测试脚本,它使用Mocha来执行我们的测试,而新的Babel包则通过支持Babel的JavaScript代码来运行所有执行的测试文件:

{
  ...
  "main": "index.js",
  "scripts": {
    "start": "nodemon --exec babel-node src/index.js",
    "test": "mocha --require @babel/register 'src/**/**spec.js'"
  },
  "keywords": [],
  ...
}

最后一个配置告诉Mocha哪些文件应该通过文件名模式匹配机制被识别为测试文件。由于我们在中间使用了** ,Mocha将递归地运行src/文件夹,以找到你的应用程序中的所有文件。在这种情况下,所有以spec.js结尾的文件都被识别为测试文件。你可以为你的测试文件选择一个不同的名称匹配(例如test.js)。

使用Chai的Node.js

Chai将是我们的断言库,用于运行平等检查或其他与测试相关的场景。它使你能够将预期结果与实际结果进行比较(例如,预期X为真)。首先,让我们把它安装在命令行上,作为我们项目的依赖项。

npm install chai --save-dev

接下来,让我们在src/spec.js文件中定义我们的第一个测试套件和测试案例。

describe('test suite', () => {
  it('test case', () => {
    ...
  });
});

到目前为止,还没有与Chai有关的东西。describe-blocks和it-blocks是由我们的测试运行器Mocha提供的。你可以在一个测试套件中拥有多个测试案例,一个测试文件也可以包含多个测试套件。通常一个测试套件用多个测试用例测试一个函数的不同结果。当我们运行我们的测试运行器时,所有的测试用例将被检查它们的断言()。

import { expect } from 'chai';

describe('true or false', () => {
  it('true is true', () => {
    expect(true).to.eql(true);
  });

  it('false is false', () => {
    expect(false).to.eql(false);
  });
});

这些测试用例并不测试我们应用程序中的任何特定逻辑,而只是演示如何用布尔运算进行平等检查。你可以用npm test从命令行中运行这两个测试,因为我们已经在package.json文件中将这个命令定义为npm脚本。

Node.js测试

到目前为止,我们还没有测试任何实现逻辑。我们之前的测试是独立的,没有任何来自我们应用程序的业务逻辑的外部依赖。然而,在一个真实的应用程序中,你想测试你的实际Node.js应用程序的逻辑。假设我们在src/sum.js文件中有一个将两个整数相加的函数,需要进行测试。

function sum(a, b) {
  return a + b;
}

export default sum;

该函数被导出,因为它被用于我们应用程序的其他部分。然而,即使它只在这一个文件中使用而没有导出语句,你仍然可以为了测试而导出它。现在,在我们的src/spec.js--或者更具体的src/sum.spec.js测试文件中,我们可以导入这个函数并进行测试。

import { expect } from 'chai';

import sum from './sum.js';

describe('sum function', () => {
  it('sums up two integers', () => {
    expect(sum(1, 2)).to.eql(3);
  });
});

恭喜你,你已经在Node.js中建立了你的第一个单元测试。当你用npm test 再次运行你的测试时,你应该在命令行上看到一个成功的测试。如果测试因为失败而变成红色,你需要检查你的业务逻辑(或测试)是否设置正确。

使用Sinon的Node.js

用Mocha中的Chai测试JavaScript原语、复杂对象和数组是一个很好的开始。最终你也会在测试函数被调用的情况下运行。因此你需要一个工具来监视、存根或模拟函数。Sinon是一个强大的库,它可以帮助你做到这一点。让我们先来看看我们要测试的用例,然后看看如何在Mocha和Chai中用Sinon进行测试。在一个新的src/call-my-function.js文件中实现以下函数。

function callMyFunction(callback) {
  callback();
}

export default callMyFunction;

这个函数只接受另一个函数作为参数--它是一个高阶函数--并简单地调用这个函数。让我们在我们的src/index.js文件中使用它。

import sum from './sum.js';
import callMyFunction from './call-my-function.js';

console.log(sum(1, 2));

callMyFunction(function() {
  console.log('Hello world');
});

我们将如何测试这个函数在其他函数中被调用?让我们在命令行上将Sinon安装为我们应用程序的node包,看看我们如何测试它。

npm install sinon --save-dev

在一个新的src/call-my-function.spec.js文件中,让我们为这个新的高阶函数编写测试。

import { expect } from 'chai';

import callMyFunction from './call-my-function.js';

describe('callMyFunction function', () => {
  it('calls the passed function', () => {
    callMyFunction(callback);

    expect(callback ???).to.eql(true);
  });
});

现在我们可以用一个Sinon spy来测试它,它被用来代替空函数:

import { expect } from 'chai';
import { spy } from 'sinon';

import callMyFunction from './call-my-function.js';

describe('callMyFunction function', () => {
  it('calls the passed function', () => {
    const callback = spy();

    callMyFunction(callback);

    expect(callback.called).to.eql(true);
  });
});

就这样了。测试应该是成功的,因为我们要测试的函数中的函数被调用了。Sinon间谍在调用后将called 的内部布尔标志从假的切换为真。你可以从Sinon的文档中了解到更多关于Spies、Mocks和Stubs的信息。


Mocha和Chai是Node.js应用程序的测试运行器和断言库的流行组合。如果你需要对函数进行断言,Sinon就会成为你的奖励。你可以在这个GitHub仓库中找到一个准备好的Node.js应用程序。如果你想更深入地进行测试,你可能想看看这个GitHub仓库,里面有一些测试,我们正在测试还原器函数。减速器的概念是JavaScript中一个流行的模式,是单元测试的最佳候选者。