Given the following code: (Note that access was promisified)
const fs = require('fs')
const util = require('util')
const access = util.promisify(fs.access)
const custom = () => {
return access('myfile', fs.constants.R_OK)
.then(() => {
return true
}).catch(err => {
if (err.code !== 'ENOENT') throw err
return false
}).then(fileExists => {
return `File exists: ${fileExists}`
})
}
module.exports = custom
My unit test is not working because the real access
method is being called instead of the stubbed one:
const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')
const custom = require('./custom')
const fs = require('fs')
const sinon = require('sinon')
chai.use(chaiAsPromised)
const expect = chai.expect
describe('custom', () => {
let sandbox = sinon.createSandbox()
afterEach(function () {
sandbox.restore()
})
it('should return file exists true', () => {
sandbox.stub(fs, 'access').yields(null)
return expect(custom()).to.eventually.equal('File exists: true')
})
it('should return file exists false', () => {
const error = new Error('No such file or directory')
error.code = 'ENOENT'
sandbox.stub(fs, 'access').yields(error)
return expect(custom()).to.eventually.equal('File exists: false')
})
})
How to make the test works, givem access
is promisified in the custom.js
file?
References:
Update Question has been updated. Answer to original question at the bottom
What you are looking for is Proxyquire . The problem is that custom.js
requires its own fs
, and you are stubbing the fs
in your test file. Proxyquire
will require a file, and replace any files/functions you want, which that file requires.
In your example, it would go something like this. (run it with mocha <test file path>
)
test file:
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const proxyquire = require('proxyquire');
chai.use(chaiAsPromised);
const expect = chai.expect;
describe('custom', () => {
let custom;
const stubs = {
fs: {
accessAsync: () => {
// Since you mentioned that fs was promisified, we will
// make this a promise as well.
return Promise.resolve();
}
},
bluebird: {
// Stop bluebird from promisifying, since we handle it above.
promisifyAll: (req => req),
}
};
before(async function () {
custom = proxyquire('./custom', stubs);
});
it('should return file exists true', () => {
return expect(custom()).to.eventually.equal('File exists: true');
});
});
custom.js
'use strict';
const bluebird = require('bluebird');
const fs = bluebird.promisifyAll(require('fs'));
module.exports = async function() {
let exists = true;
await fs.accessAsync('nonimportant.path', fs.constants.F_OK)
.catch( () => { exists = false; });
return `File exists: ${exists}`;
};
Original answer
No need to use bluebird in this case, Sinon can handle that.
You need to use the sinon.stub() function. It can be done like this:
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const sinon = require('sinon');
const fs = require('fs');
chai.use(chaiAsPromised);
const expect = chai.expect;
describe('fs.stat', function(){
before(function() {
sinon.stub(fs, 'stat').resolves('Your desired value');
});
it('should should be called', function(done){
expect(fs.stat('./some.file'))
.to.eventually.equal('Your desired value')
.notify(done);
});
});
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.