Edited Question with vazsonyidl suggestions applied
I have to write unit tests for a function similar to this one:
import {External} from 'ExternalModule'; async functionA(){ this.functionB().then((data) => { External.functionC(options); console.log("Reached1"); }).catch((data) => { const { OnError = "" } = data || {} if(OnError) { External.functionC(anotherOptions); console.log("Reached2"); } }) } functionB() { return new Promise(() => { }); }
As functionC belongs to another module, I placed a mock of it in the _mocks_
folder:
//_mocks_/ExternalModule.ts export var External: ExternalClass = { functionC(){} } class ExternalClass{ constructor(){}; functionC(){}; }
I have mocked functionB in two diferent ways for testing the then
and the catch
:
it("should test then block", () => { functionB = jest.fn(() => {return Promise.resolve()}); const functionSpy = jest.spyOn(ExternalModule.External, 'functionC'); void functionA().then(() => { expect(functionSpy).not.toHaveBeenCalled(); }); }) it("should test catch block", () => { const err = { OnError: "Error" }; functionB = jest.fn(() => {return Promise.reject(err)}); const functionSpy = jest.spyOn(ExternalModule.External, 'functionC'); void functionA().then(() => { expect(functionSpy).not.toHaveBeenCalled(); }); })
What I am trying to do is expect that functionC was called and called with the correct params, but the test is always passing even if I test if functionC was not called.
What am I doing wrong?
Advertisement
Answer
Jest does not wait for the async code to complete before doing assertions.
You can use the following function:
const waitForPromises = () => new Promise(setImmediate);
to force Jest to wait for promises to complete before continuing like so:
it("does something", async () => { promiseCall(); await waitForPromises(); expect(something).toBe(something) });