I have a function (hostelService.book
) that returns a promise: return Promise.resolve(response);
and I made this test:
const action = async () => {
await hostelService.book(id);
};
await expect(action).rejects.toThrow();
but I have this error:
Matcher error: received value must be a promise
Testing try catch errors We have a mock function and we want to test whether it throws the error we are expecting. We can do this by simply passing the function to the expect without actually invoking it, and calling the toThrow method on it with the passed error.
When you're writing tests, you often need to check that values meet certain conditions. expect gives you access to a number of "matchers" that let you validate different things. For additional Jest matchers maintained by the Jest Community check out jest-extended .
expect. assertions(number) verifies that a certain number of assertions are called during a test. This is often useful when testing asynchronous code, in order to make sure that assertions in a callback actually got called.
In Jest you have to pass a function into expect(function). toThrow(<blank or type of error>) . Example: test("Test description", () => { const t = () => { throw new TypeError(); }; expect(t).
Jest is throwing this error Matcher error: received value must be a promise
because in expect
you are just passing the function reference. Without ()
- action
is just a function reference it will not return anything.
To fix this issue you have to call the function in expect like action()
so it will return the promise object.
And the second part, you have to throw error like. Promise.reject(new Error('some error'));
in the reject so the tothrow
condition can be full filled.
Example:
function hostelService() {
return Promise.reject(new Error('some error'));
}
const action = async () => {
await hostelService();
};
it( "Should throw the error", async () => {
await expect(action()).rejects.toThrow('some error');
});
Hope this will be helpful.
Your test fails because you're awaiting the promise (and therefore, it is no longer a Promise when you call .rejects
on it). If you remove await
from the last statement, it should do the trick:
const action = async () => {
await hostelService.book(id);
};
expect(action()).rejects.toThrow();
Here is some rationale behind it. async
automatically wraps your return type into a Promise. However, when you call await
, it synchronously "unwraps" the value of a given Promise and therefore it can't call .rejects
on the result (unless you wrap a Promise into another Promise).
I've composed a small example to illustrate what I mean.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With