Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test the type of a thrown exception in Jest

I'm working with some code where I need to test the type of an exception thrown by a function (is it TypeError, ReferenceError, etc.?).

My current testing framework is AVA and I can test it as a second argument t.throws method, like here:

it('should throw Error with message \'UNKNOWN ERROR\' when no params were passed', (t) => {
  const error = t.throws(() => {
    throwError();
  }, TypeError);

  t.is(error.message, 'UNKNOWN ERROR');
});

I started rewriting my tests in Jest and couldn't find how to easily do that. Is it even possible?

like image 772
bartsmykla Avatar asked Sep 04 '17 18:09

bartsmykla


People also ask

How do you test throw error 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).

What type of error is thrown if the test fails?

In this case, the test will fail because the WebDriver could not find the element. In this case, StaleElementReferenceException will be thrown.

How do you test a method in Jest?

To test method implementation using spies with Jest we use the jest. spyOn() function. jest. spyOn() is called with two required parameters - the object and the object method identifier we're spying on.

What is Tohavebeencalled in Jest?

Jest function toHaveBeenCalledWith to ignore object order. 3. Jest to match every object in array.


3 Answers

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).toThrow(TypeError);
});

Or if you also want to check for error message:

test("Test description", () => {
  const t = () => {
    throw new TypeError("UNKNOWN ERROR");
  };
  expect(t).toThrow(TypeError);
  expect(t).toThrow("UNKNOWN ERROR");
});

If you need to test an existing function whether it throws with a set of arguments, you have to wrap it inside an anonymous function in expect().

Example:

test("Test description", () => {
  expect(() => {http.get(yourUrl, yourCallbackFn)}).toThrow(TypeError);
});
like image 175
PeterDanis Avatar answered Oct 23 '22 04:10

PeterDanis


It is a little bit weird, but it works and IMHO is good readable:

it('should throw Error with message \'UNKNOWN ERROR\' when no parameters were passed', () => {
  try {
      throwError();
      // Fail test if above expression doesn't throw anything.
      expect(true).toBe(false);
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

The Catch block catches your exception, and then you can test on your raised Error. Strange expect(true).toBe(false); is needed to fail your test if the expected Error will be not thrown. Otherwise, this line is never reachable (Error should be raised before them).

@Kenny Body suggested a better solution which improve a code quality if you use expect.assertions():

it('should throw Error with message \'UNKNOWN ERROR\' when no parameters were passed', () => {
  expect.assertions(1);
  try {
      throwError();
  } catch (e) {
      expect(e.message).toBe("UNKNOWN ERROR");
  }
});

See the original answer with more explanations: How to test the type of a thrown exception in Jest

EDIT 2022:

To use this approach and not trigger no-conditional-expect rule (if you're using eslint-plugin-jest), documentation of this rule suggest to use error wrapper:

class NoErrorThrownError extends Error {}

const getError = async <TError>(call: () => unknown): Promise<TError> => {
  try {
    await call();

    throw new NoErrorThrownError();
  } catch (error: unknown) {
    return error as TError;
  }
};

describe('when the http request fails', () => {
  it('includes the status code in the error', async () => {
    const error = await getError(async () => makeRequest(url));

    // check that the returned error wasn't that no error was thrown
    expect(error).not.toBeInstanceOf(NoErrorThrownError);
    expect(error).toHaveProperty('statusCode', 404);
  });
});

See: no-conditional-expect docs

like image 29
Paweł BB Drozd Avatar answered Oct 23 '22 05:10

Paweł BB Drozd


I use a slightly more concise version:

expect(() => {
  // Code block that should throw error
}).toThrow(TypeError) // Or .toThrow('expectedErrorMessage')
like image 122
Tal Joffe Avatar answered Oct 23 '22 06:10

Tal Joffe