Reputation: 2927
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?
Upvotes: 0
Views: 697
Reputation: 151380
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:
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);
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);
});
});
Upvotes: 1