I've managed to successfully test a basic express server, a function returning promises, and a basic sequelize setup to get my nose wet; but I am stuck on spies/stubs/mocks.
My fist hiccup is trying to check that glob has been called in an external module:
//in utils.js
var glob = require('glob');
module.exports = {
funToTest: function (msg, callback) {
console.log(msg);
glob('*md', {
cwd: 'files/'
}, function (err, files) {
console.log(files);
});
callback();
callback();
}
};
Using a mocha/chai/sinon/sinon-chai combination:
// in utils-test.js
var utils = require('utils.js');
var glob = require('glob');
describe('Utils', function () {
describe('funToTest method', function () {
const callback = sinon.spy();
const globSpy = sinon.spy(glob);
before(function (done) {
utils.funToTest('Files:', callback);
done();
});
// This PASSES fine
it ('should call our callback twice', function () {
expect(callback).to.have.been.calledTwice;
});
// This NOT SO MUCH
it('should call glob once', function () {
expect(globSpy).to.have.been.calledOnce;
});
)};
)};
The above fails with an assertion error:
AssertionError: expected glob to have been called exactly once, but it was called 0 times
So how do I spy on the glob dependency in utils.funToTest
to see if gets called?
You're spying on the glob module itself, not the glob call within your funToTest
method. The problem is that the glob call is an implementation detail and is not actually accessible from within your test. You'd need to pass in an argument for the glob callback and test that it was called with a spy or stub.
//in utils.js
var glob = require('glob');
module.exports = {
funToTest: function (msg, globCb, callback) {
glob('*md', {
cwd: 'files/'
}, globCb);
callback();
callback();
}
};
// in utils-test.js
var utils = require('utils.js');
var glob = require('glob');
describe('Utils', function () {
describe('funToTest method', function () {
const callback = sinon.spy();
const globCb = sinon.spy();
const err = {err: 'Error'};
const files = ['file1', 'file2'];
before(function (done) {
utils.funToTest('Files:', globCb, callback);
done();
});
// Should still pass
it ('should call our callback twice', function () {
expect(callback).to.have.been.calledTwice;
});
// Passes with correct args
it('should call glob once', function () {
expect(globCb).to.have.been.calledOnce;
// inspect the arg values with .calledWithArgs
expect(globCb.calledWithArgs(err, files)).to.be.true;
// inspect the arg values with .getCall(index) (actually grabs the call args on the first call to globSpy)
expect(globCb.getCall(0).args[0]).to.equal(err);
expect(globCb.getCall(0).args[1]).to.equal(files);
});
)};
)};
Here is the unit test solution using additional library proxyquire
:
utils.js
:
const glob = require("glob");
module.exports = {
funToTest: function(msg, callback) {
console.log(msg);
glob(
"*md",
{
cwd: "files/",
},
function(err, files) {
console.log(files);
},
);
callback();
callback();
},
};
utils.test.js
:
const proxyquire = require("proxyquire");
const sinon = require("sinon");
describe("36477213", () => {
afterEach(() => {
sinon.restore();
});
it("should pass", () => {
const logSpy = sinon.spy(console, "log");
const files = ["a", "b"];
const globStub = sinon.stub().yields(null, files);
const utils = proxyquire("./utils.js", {
glob: globStub,
});
const callback = sinon.stub();
utils.funToTest("some message", callback);
sinon.assert.calledWith(globStub, "*md", { cwd: "files/" }, sinon.match.func);
sinon.assert.calledTwice(callback);
sinon.assert.calledWith(logSpy.firstCall, "some message");
sinon.assert.calledWith(logSpy.secondCall, files);
});
});
Unit test result with 100% coverage:
36477213
some message
[ 'a', 'b' ]
✓ should pass
1 passing (24ms)
---------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
utils.js | 100 | 100 | 100 | 100 | |
utils.test.js | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/36477213
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.