I'm trying to do call a function that is imported as a function independently in another function that I'm calling from my unit test. How can I get callcount of 1 on the functionIWantToSpy in this scenario?
auditEvent.js:
const { verify } = require('@mycompany/verifylib');
const { functionIWantToSpy } = require('@mycompany/another-lib');
const auditEvent = () => {
verify();
functionIWantToSpy();
};
module.exports = { auditEvent };
test:
const { verify } = require('@mycompany/verify-lib');
const { functionIWantToSpy } = require('@mycompany/another-lib');
describe('mytest', () => {
let spiedFuntion;
let verifyStub;
beforeEach(() => {
verifyStub = sinon.stub();
({auditEvent} = proxyquire('./auditEvent', {
'@mycompny/verify-lib': {
verify: verifyStub,
'@noCallThru': true,
},
}));
spiedFunction = sinon.spy(functionIWantToSpy);
});
it('should work'), async () => {
auditEvent();
expect(functionIWantToSpy).to.have.callCount(1); // Getting callcount of 0 here...
});
});
Spying involves replacing the function with a new function. You are replacing what is referred to by the identifier functionIWantToSpy
so that it refers to a new spy function, instead of the original function referred to by require('@mycompany/another-lib').functionIWantToSpy
. The code inside the module can't see your new spy function. The expression require('@mycompany/another-lib').functionIWantToSpy
refers to the original function, unchanged.
Because require
caches results (i.e., only the first require("foo")
executes foo
, and any subsequent require("foo")
summons up that same object returned by the first require
call), you can modify the functionIWantToSpy
method of the require('@mycompany/another-lib')
object, using the two-argument form of sinon.spy
:
spiedFunction = sinon.spy(require('@mycompany/another-lib'), "functionIWantToSpy");
You must do this before the property is ever accessed (and value stored) by the module being tested:
verifyStub = sinon.stub();
// IMPORANT: FIRST, spy the functionIWantToSpy property on the required object before importing auditEvent
spiedFunction = sinon.spy(require('@mycompany/another-lib'), "functionIWantToSpy");
({auditEvent} = proxyquire('./auditEvent', {
'@mycompny/verify-lib': {
verify: verifyStub,
'@noCallThru': true,
},
}));
This should work because when the auditEvent module runs for the first time and gets to
const { functionIWantToSpy } = require('@mycompany/another-lib');
then require('@mycompany/another-lib').functionIWantToSpy
will refer to the spy function.