使用 Mocha、Chai、chaiAsPromised 和 Sinon 测试 js promises

Testing js promises with Mocha, Chai, chaiAsPromised and Sinon

我正在尝试测试读取文件的函数和 returns 对文件内容的承诺。

function fileContents(){
  return new Promise(function(resolve, reject) {
    fs.readFile(filename, function(err, data){
      if (err) { reject(err); }
      else { resolve(data); }
    });
  });
}

上面的单元测试

describe('Testing fileContents', function () {

afterEach(function () {
    fs.readFile.restore();
});

it('should return the contents of the fallBack file', function () {
    let fileContents = '<div class="some-class">some text</div>';

    sinon.stub(fs, 'readFile').returns(function(path, callback) {
        callback(null, fileContents);
    });

    let fileContentsPromise = fileContents();

    return fileContentsPromise
      .then(data => {
        expect(data).to.eventually.equal(fileContents);
      });

 });

以上测试错误

 Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves.

我也试过了

describe('Testing fileContents', function () {

  afterEach(function () {
    fs.readFile.restore();
  });

  it('should return the contents of the fallBack file', function (done) {
    let fileContents = '<div class="some-class">some text</div>';

    sinon.stub(fs, 'readFile').returns(function(path, callback) {
        callback(null, fileContents);
    });

    let fileContentsPromise = fileContents();

  fileContentsPromise.then(function(data){
    expect(data).to.equal(fileContents);
    done();
  });
});

并得到同样的错误。该功能在我的本地站点上运行,但我不知道如何为其编写测试。我是js的新手。我错过了什么?

您的代码存在多个问题。例如,您在测试中重新声明 fileContents 并为其分配一个字符串值,这当然不适用于在同一测试中执行 fileContents() 。我将专注于两个概念性问题,而不是像这个 "duh" 类型的错误。

两个概念性问题是:

  1. 要让 fs.readFile 使用假值调用您的回调,您必须使用 .yields。使用 .returns 会更改您未使用的 return 值。所以像这样存根:

    sinon.stub(fs, 'readFile').yields(null, fakeContents);
    
  2. 您正在 non-promise 上使用 chai-as-promised 提供的 .eventually 功能,但您必须承诺使用它才能正常工作,所以你的测试应该是:

    return expect(fileContentsPromise).to.eventually.equal(fakeContents);
    

这是有效的代码:

const sinon = require("sinon");
const fs = require("fs");
const chai = require("chai");
const chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);

const expect = chai.expect;

// We need to have filename defined somewhere...
const filename = "foo"; 
function fileContents(){
  return new Promise(function(resolve, reject) {
    fs.readFile(filename, function(err, data){
      if (err) { reject(err); }
      else { resolve(data); }
    });
  });
}

describe('Testing fileContents', function () {

    afterEach(function () {
        fs.readFile.restore();
    });

    it('should return the contents of the fallBack file', function () {
        let fakeContents = '<div class="some-class">some text</div>';

        sinon.stub(fs, 'readFile').yields(null, fakeContents);

        let fileContentsPromise = fileContents();

        return expect(fileContentsPromise).to.eventually.equal(fakeContents);
    });
});