Search code examples
javascripttestingjestjsts-jest

How to mock non-async method for throwing an exception with Jest?


Here is a fragment from my code in TypeScript:

let myService: MyService;
let myController: MyController;

beforeAll(async function () {
    myService = new MyService(null);
    myController = new MyController(myService);
});

it("should fail due to any 'MyService' error", () => {
    jest.spyOn(myService, 'create').mockImplementation(() => {
        throw new Error(); // ! the test fails here
    });
    expect(myController.create(data)).toThrowError(Error);
});

The create method of MyController is not async, neither is of MyService: both are just regular methods. Now when I try to run this test it fails on the line of the mocked method where the exception is thrown: throw new Error() and it works correctly only if I wrap the create method call with try/catch like this:

try {
    expect(myController.create(data)).toThrowError(Error);
}
catch { }

It looks very strange to me. Shouldn't it work without wrapping in try/catch by design?


Solution

  • You just need a small change.


    From the .toThrowError doc:

    Use .toThrowError to test that a function throws when it is called.


    You are passing the result of calling myController.create(data).

    You need to pass a function that throws when it is called, in this case:

    () => { myController.create(data); }
    

    Change your expect line to this:

    expect(() => { myController.create(data); }).toThrowError(Error);  // SUCCESS
    

    ...and it should work.