Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expect a function to throw an exception in Jest

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
like image 647
Sandro Rey Avatar asked Jan 15 '20 08:01

Sandro Rey


People also ask

How do you expect a function to throw an error in Jest?

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.

What is expect in Jest?

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 .

What is expect assertions in Jest?

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.

How do I see exceptions in Jest?

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).


2 Answers

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.

like image 55
Sohail Ashraf Avatar answered Oct 05 '22 11:10

Sohail Ashraf


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.

like image 40
Alexey Kureev Avatar answered Oct 05 '22 10:10

Alexey Kureev