typescripttypesjestjsmocking

Mocking an error throwing function in jest


I am trying to create a mock for a function that throws a particular error:

throwCycleDetected(ticket: string): never {
 throw new HttpException ()
}

However when I try to mock the function with jest:

throwerGuard.throwCycleDetected = jest
  .fn()
  .mockImplementation(() => {
    throw new Error('Detected a cycle of tickets for ticketId')
  }) 

I get an error:

Type 'Mock<any, any, any>' is not assignable to type '(ticketId: string) => never'. Type 'any' is not assignable to type 'never'.ts(2322)

Can you please help me figure out how am I supposed to mock a function like this without removing the type notation?

I removed the type notation from the function and it allowed the mock to work, but I don't really understand why it is necessary to remove it and I would prefer a solution which allows me to keep the type notation on the function.


Solution

  • never type is quite tricky when it comes to mocks. I would recommend rather using jest.spyOn to mock the function.

    jest.spyOn(throwerGuard, "throwCycleDetected").mockImplementation(() => {
      throw new Error("Detected a cycle of tickets for ticketId");
    });
    

    This way you don't interfere with a method via direct assignment and preserve the never type without any issues.

    If you would like to keep the direct assignment, then you'd have to do something like this:

    // Using `unknown` as an intermediary type to satisfy TypeScript
        throwerGuard.throwCycleDetected = jest.fn().mockImplementation(() => {
          throw new Error("Detected a cycle of tickets for ticketId");
        }) as unknown as (ticketId: string) => never;
    

    You need to explicitly type the function, but with an intermediary unknown conversion. Typing as (ticketId: string) => never; produced another typescript error, which states that any can't be converted to never.