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…
1
3 Answers
Reset to default
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
2
-
1
cool. How to handle it and make and assert?
– DmytroFeb 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?
– schlingelMar 7, 2022 at 7:36
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()
})
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 DeveloperNov 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
– gawkfaceNov 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.
– CortexCompilerAug 10, 2022 at 19:31
For Angular + Jest:
import { throwError } from 'rxjs';
yourMockInstance.mockImplementation(() => {
return throwError(new Error('my error message'));
});
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 LysobeySep 16, 2020 at 21:57
-
Only returning
throw Error
should be enough:yourMockInstance.mockImplementation(() => throwError('my error message'));
– manzapanzaApr 30, 2021 at 21:42
-
Actually using
mockReturnValue
is enough:mockInstance.mockReturnValue(throwError(() => new Error('my error message')))
– RcoderNYJun 19, 2022 at 5:41
Not the answer you’re looking for? Browse other questions tagged
or ask your own question.
or ask your own question.
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?
May 14, 2018 at 13:54
|