Galty
Galty

Reputation: 37

How to mock a method or function to return an expected error

Trying to learn how to write better tests with Jest/Typescript. I would like to ensure that I can test for an error.

I can create mocked method that will return an expected array of data, however testing for errors is proving difficult.

//program.ts
const listStacks = async (cf: CloudFormation): Promise<StackSummaries> => {
  try {
        const result = await cf.listStacks().promise();
        if (result.StackSummaries) {
          return result.StackSummaries;
        }
        return [];
  } catch(e) {
        console.log(e);
        throw e;  
  }

Here is my test below, note i've tried returning a new Error instead of a throw but that doesn't appear to work either.

//program.test.js
it('handles errors gracefully', async () => { 
    expect.assertions(1);
    const cfMock = {
        listStacks: (): any => ({
            promise: async () => {
                    throw new Error('ohh NOO!');             
            }
        })
    }
    expect(() => listStacks(cfMock as CloudFormation)).toThrow();

Jest returns this:

expect(received).toThrow()

Received function did not throw . 

Upvotes: 1

Views: 2740

Answers (2)

Brian Adams
Brian Adams

Reputation: 45810

listStacks is an async function.

async functions return the following:

A Promise which will be resolved with the value returned by the async function, or rejected with an uncaught exception thrown from within the async function.

In this case you are providing a mock which causes an uncaught exception to be thrown within the async function, so it will return a Promise which will reject with the uncaught exception.

To verify this behavior change your expect line to the following:

await expect(listStacks(cfMock)).rejects.toThrow();  // SUCCESS

Note that toThrow was fixed for promises with PR 4884 so if you are using an older version of Jest (before 22.0.0) you will need to use something like toEqual:

await expect(listStacks(cfMock)).rejects.toEqual(expect.any(Error));  // SUCCESS

Upvotes: 1

Rafael Rocha
Rafael Rocha

Reputation: 518

Try to place the throw statement inside the operation made in the try block. for example:

  if(!result.StackSummaries) {
    throw new Error('error message to assert') 
  }

The catch block will catch any error thrown in the try block, so you can mock the return of listStacks to be null so that it falls on that if and throws the error.

Upvotes: 0

Related Questions