简体   繁体   中英

Testing js promises with Mocha, Chai, chaiAsPromised and Sinon

I'm trying to test a function that reads in a file and returns a promise with the file's contents.

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

The unit test for the above

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);
      });

 });

The above test errs with

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

I also tried

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();
  });
});

and got the same error. The function is working in my local site, but I don't know how to write a test for it. I'm new to js. What am I missing?

There are multiple problems with your code. For instance, you redeclare fileContents in your test and assign it a string value, which of course won't work with doing fileContents() in the same test. I'm going to concentrate on two conceptual problems rather than the "duh"-type mistakes like this one.

The two conceptual problems are:

  1. To have fs.readFile call your callback with fake values you must use .yields . Using .returns changes the return value, which you do not use. So stub it like this:

     sinon.stub(fs, 'readFile').yields(null, fakeContents); 
  2. You are using the .eventually functionality provided by chai-as-promised on a non-promise, but you have to use it on a promise for it to work properly so your test should be:

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

Here's code that works:

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);
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM