How to properly make mock throw an error in Jest?

How to properly make mock throw an error in Jest?

176

I’m testing my GraphQL api using Jest.

I’m using a separate test suit for each query/mutation

I have 2 tests (each one in a separate test suit) where I mock one function (namely, Meteor’s callMethod) that is used in mutations.

  it('should throw error if email not found', async () => {
    callMethod
      .mockReturnValue(new Error('User not found [403]'))
      .mockName('callMethod');

    const query = FORGOT_PASSWORD_MUTATION;
    const params = { email: '[email protected]' };

    const result = await simulateQuery({ query, params });

    console.log(result);

    // test logic
    expect(callMethod).toBeCalledWith({}, 'forgotPassword', {
      email: '[email protected]',
    });

    // test resolvers
  });

When I console.log(result) I get

{ data: { forgotPassword: true } }

This behaviour is not what I want because in .mockReturnValue I throw an Error and therefore expect result to have an error object

Before this test, however, another is ran

 it('should throw an error if wrong credentials were provided', async () => {
    callMethod
      .mockReturnValue(new Error('cannot login'))
      .mockName('callMethod');

And it works fine, the error is thrown

I guess the problem is that mock doesn’t get reset after the test finishes.
In my jest.conf.js I have clearMocks: true

Each test suit is in a separate file, and I mock functions before tests like this:

import simulateQuery from '../../../helpers/simulate-query';

import callMethod from '../../../../imports/api/users/functions/auth/helpers/call-accounts-method';

import LOGIN_WITH_PASSWORD_MUTATION from './mutations/login-with-password';

jest.mock(
  '../../../../imports/api/users/functions/auth/helpers/call-accounts-method'
);

describe('loginWithPassword mutation', function() {
...

UPDATE

When I substituted .mockReturnValue with .mockImplementation everything worked out as expected:

callMethod.mockImplementation(() => {
  throw new Error('User not found');
});

But that doesn’t explain why in another test .mockReturnValue works fine…

Share
Improve this question

1

  • 1

    It looks like your mock is returning an error object, not throwing it. Without seeing your code that you are testing, I can only share the experience I had. I forgot to mock a function called in my mutation, which caused an error to be thrown unintentionally. Perhaps there is something similar happening for you?

    – Rhuarc13

    May 14, 2018 at 13:54

3 Answers
3

Reset to default

305

Change .mockReturnValue with .mockImplementation:

    yourMockInstance.mockImplementation(() => {
      throw new Error();
    });

in case you want to assert

   test('the fetch fails with an error', () => {
     return expect(fetchData()).rejects.toMatch('error');
   });

If it’s a promise you can also to .rejects www.jestjs.io/docs/en/asynchronous#resolves–rejects

Share
Improve this answer

2

  • 1

    cool. How to handle it and make and assert?

    – Dmytro

    Feb 19, 2021 at 23:00

  • 2

    it throws the error but then the test fails because it has thrown an error. how do we assert?

    – schlingel

    Mar 7, 2022 at 7:36

33

For promises, can use https://jestjs.io/docs/mock-function-api#mockfnmockrejectedvaluevalue

test('async test', async () => {
  const asyncMock = jest.fn().mockRejectedValue(new Error('Async error'));

  await asyncMock(); // throws "Async error"
});

For testing that error was thrown or not, can use https://eloquentcode.com/expect-a-function-to-throw-an-exception-in-jest

const func = () => {
  throw new Error('my error')
}
it('should throw an error', () => {
    expect(func).toThrow()
})

Share
Improve this answer

3

  • 1

    You would also need a try and catch in your expect otherwise it would not assert correctly. Can you please improve your answer or reply if I am missing something.

    – MG Developer

    Nov 24, 2021 at 16:57

  • 1

    @MGDeveloper we dont need try-catch while unit testing and using toThrow() (jestjs.io/docs/expect#tothrowerror). If you try that in your tests, it should work. Can also test in here : codesandbox.io/s/jest-playground-forked-euewe?file=/src/… (sandbox content is transient though). I did edit the terminology from “handling” to “testing” if that was confusing

    – gawkface

    Nov 27, 2021 at 3:42


  • 1

    I found the mockRejectedValue helpful in the case that the asynchronous unit I was testing handled the exception thrown in a specific way that I wanted to test, therefore in that case a catch or toThrow() would not be needed.

    – CortexCompiler

    Aug 10, 2022 at 19:31

12

For Angular + Jest:

import { throwError } from 'rxjs';

yourMockInstance.mockImplementation(() => {
  return throwError(new Error('my error message'));
});

Share
Improve this answer

3

  • 2

    Technically this isn’t a throw in the pure JS sense. You are configuring the mock to return a RXJS observable object which immediately emits an error notification. Still, maybe handy for folks to see here. The accepted answer certainly will make a mock throw an error. In all cases.

    – Zach Lysobey

    Sep 16, 2020 at 21:57


  • Only returning throw Error should be enough: yourMockInstance.mockImplementation(() => throwError('my error message'));

    – manzapanza

    Apr 30, 2021 at 21:42

  • Actually using mockReturnValue is enough: mockInstance.mockReturnValue(throwError(() => new Error('my error message')))

    – RcoderNY

    Jun 19, 2022 at 5:41



Your Answer


Post as a guest

Required, but never shown


By clicking тАЬPost Your AnswerтАЭ, you agree to our terms of service, privacy policy and cookie policy

Not the answer you’re looking for? Browse other questions tagged

or ask your own question.

Leave a Reply

Your email address will not be published. Required fields are marked *