I'm using sinon
and I want to do something very simple, and I cannot find any solution after a lot of searching.
I have class MessageService
class looks like this:
import sb from "@azure/service-bus";
export class MessageService {
async handleNewMessage() {
//some code ....
await sb.delay(5000);
//some code ....
}
}
I want to test the handleNewMessage
method , but inside there is call to third party library sb.delay(5000)
(that actually sleep for 5s)
I want to replace this function and make it to do nothing.
In my messageService.spec.js
file I tried to import it and replace it, but it's not working.
import sb from "@azure/service-bus";
describe('message service', () => {
beforeEach(() => {
sinon.stub(sb, 'delay').returns(()=>{});
});
afterEach(() => {
sinon.restore();
});
it("handleNewMessage should work", async () => {
//This is call to the real sb.delay function
await messageServiceMock.handleNewMessage();
});
})
Is there any way to replace the original class third party function call?
From this comment: https://github.com/sinonjs/sinon/issues/1711#issuecomment-369220753
we're not allowed to modify modules that are imported using import. It looks like imports are read-only views on exports.
So, sinon.stub is not able to modify the imported module.
Take a look at sb.delay
implementation:
export function delay<T>(t: number, value?: T): Promise<T> {
return new Promise(resolve => setTimeout(() => resolve(value), t));
}
//...
export { delay }
Here is the solution:
MessageService.ts
:
import * as sb from "@azure/service-bus";
export class MessageService {
async handleNewMessage() {
await sb.delay(5000);
}
}
MessageService.test.ts
:
import sinon from "sinon";
import proxyquire from "proxyquire";
describe("message service", () => {
afterEach(() => {
sinon.restore();
});
it("handleNewMessage should work", async () => {
const delayStub = sinon.stub().resolves({});
const { MessageService } = proxyquire("./MessageService.ts", {
"@azure/service-bus": {
delay: delayStub,
},
});
const messageServiceMock = new MessageService();
await messageServiceMock.handleNewMessage();
sinon.assert.calledWith(delayStub, 5000);
});
});
Unit test result with 100% coverage:
message service
✓ handleNewMessage should work (1343ms)
1 passing (1s)
------------------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
------------------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
MessageService.test.ts | 100 | 100 | 100 | 100 | |
MessageService.ts | 100 | 100 | 100 | 100 | |
------------------------|----------|----------|----------|----------|-------------------|
Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59234255