Jest's expect method fails to capture errors thrown by async/await functions

I'm currently experimenting with a TypeScript-Express application that utilizes MongoDB and Mongoose. To perform testing, I have integrated jest and mongo-memory-server into the project. While I have succeeded in testing the insertion of new documents and retrieving existing ones from the database, I am facing difficulty in handling errors when attempting to retrieve a document that does not exist.

const getUserByEmail = async (email: string): Promise<UserType> => {
  try {
    const user = await User.findOne({ email });
    if (!user) {
      const validationErrorObj: ValidationErrorType = {
        location: 'body',
        param: 'email',
        msg: 'User with this email does not exist!',
        value: email,
      };
      const validationError = new ValidationError('Validation Error', 403, [
        validationErrorObj,
      ]);
      throw validationError;
    }
    return user;
  } catch (err) {
    throw new Error(err);
  }
};


let mongoServer: any;
describe('getUserByEmail', (): void => {
  let mongoServer: any;
  const opts = {}; // remove this option if you use mongoose 5 and above
  const email = '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9de9f8eee9ddf0fcf4f1b3fef2f0">[email protected]</a>';
  const password = 'testPassword';
  const username = 'testUsername';

  beforeAll(async () => {
    mongoServer = new MongoMemoryServer();
    const mongoUri = await mongoServer.getConnectionString();
    await mongoose.connect(mongoUri, opts, err => {
      if (err) console.error(err);
    });
    const user = new User({
      email,
      password,
      username,
    });
    await user.save();
  });

  afterAll(async () => {
    mongoose.disconnect();
    await mongoServer.stop();
  });

  it('fetching registered user', async (): Promise<void> => {
    const user = await getUserByEmail(email);
    expect(user).toBeTruthy();
    expect(user.email).toMatch(email);
    expect(user.password).toMatch(password);
    expect(user.username).toMatch(username);
  }, 100000);
  it('attempting to fetch non-registered user', async (): Promise<void> => {
    const notRegisteredEmail = '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b6c5d9dbd3f6dbd7dfda98d5d9db">[email protected]</a>';
    expect(await getUserByEmail(notRegisteredEmail)).toThrowError();
  }, 100000);
});

Answer №1

After facing a similar problem, I found success with the following solution:

await expect(asyncFuncWithError()).rejects.toThrow(Error)

Answer №2

After some searching, I managed to locate the solution on GitHub's Jest issues

it('fetching non registered user', async (): Promise<void> => {
    const nonRegisteredEmail = 'nonREgisteredEmail.com';
    await expect(getUserByEmail(nonRegisteredEmail)).rejects.toThrow(
      new Error('Error: Validation Error'),
    );
  }, 100000);

Answer №3

After encountering this issue in the past, I've discovered that using an anonymous function as a parameter can resolve it:

const throwFn = () => { throw new Error() };

// initial attempt
it('should throw', () => {
  expect(throwFn()).toThrow();
});

// successful workaround
it('should throw', () => {
  expect(() => throwFn()).toThrow();
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Express: a logical approach to routing

Is there a way to set up a regular expression with OR conditions in Express (v4.15) routing? I would like the following paths to lead to the same function /video/:videoId /movies/:videoId /media/:videoId When I attempted app.get('/(video|media|mo ...

Guide on how to execute jasmine tests coded in TypeScript for Node.js applications

I am eager to test my express application developed in TypeScript. I am utilizing jasmine for writing test cases, webpack for bundling TypeScript files to JavaScript, and karma as the test runner. Please locate the following files: // about.service.ts - ...

When CRA is embedded within an Express app, it disrupts the normal routing of

I have developed a CRA app with several express routes that load the CRA build files. Here's an example of one of the routes: app.get('/files', async (req, res, next) => { ... try { res.format({ ...

Issue with Socket.IO: socket.on not executed

Recently, I devised a custom asynchronous emitter for implementing a server -> client -> server method. Regrettably, the functionality is not meeting my expectations. Although it emits the event, it fails to execute the callback as intended. Upon a ...

Using async/await with mysql2 in Node.js can lead to undefined rows and fields

I am facing an issue where the query below is returning undefined in rows and field even though the user table has data. How can I properly use the promise version in TypeScript? Any help would be greatly appreciated. Thank you... code import mysql from ...

An issue occurred in NestJs where it was unable to access the property '__guards__' because it was undefined

Currently, I am in the process of incorporating a basic authentication system into my Nest project. After including the following line in my controller: @UseGuards(AuthGuard('local')) I encountered this error message: ERROR [ExceptionHandler] C ...

How can I create an interceptor in Angular2 to detect 500 and 404 errors in my app.ts file?

Creating an Angular2 Interceptor for Handling 500 and 404 Errors in app.ts In my app.ts file, I am looking to implement an interceptor that can detect a 500 or 404 error so that I can appropriately redirect to my HTML 404 or HTML 500 pages. Is this funct ...

Ways to rename a sequelize property following a join operation

I am encountering a problem with sequelize ORM. The data returned after joining has a nested object: { "id": 1, "username": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="4125342e2f26252e282220 ...

Is it necessary to revert back to an older Node.js version in order to successfully install Mail

Utilizing the Mailjet library necessitates Node.js version 4.0, 4.1, 5.0.0, or 6.11.1. My current Node.js version is v14.16.1, which seems like a significant downgrade from the required versions. This raises concerns about security and potential impacts on ...

Is it possible to use identical path names for different methods within a REST API?

For my REST API development, I am utilizing Swagger api. I am currently working on creating methods for inserting, updating, and deleting data in a similar format commonly found in many online APIs: POST (insert) /students PUT (update) /students/{stu ...

Creating two number-like types in TypeScript that are incompatible with each other can be achieved by defining two

I've been grappling with the challenge of establishing two number-like/integer types in TypeScript that are mutually incompatible. For instance, consider the following code snippet where height and weight are both represented as number-like types. Ho ...

The functionality of the String prototype is operational in web browsers, but it encounters issues

Version: 8.1.0 The prototype I am working with is as follows: String.prototype.toSlug = function () { return (<string>this) .trim() .toLowerCase() .replace(/\s+/g, '-') .replace(/[^\w\-]+/g, '') ...

The variable 'string' has been declared, but it is never utilized or accessed

Currently delving into Typescript and facing an early error. Despite following a tutorial, I'm encountering multiple errors that I have attempted to comment out. Would greatly appreciate it if someone could shed some light on why these errors are occu ...

What are the security benefits of using Res.cookie compared to document.cookie?

When it comes to setting cookies to save data of signed in members, I faced a dilemma between two options. On one hand, there's res.cookie which utilizes the Express framework to set/read cookies on the server-side. On the other hand, there's d ...

Middleware in Express that performs an asynchronous operation that is executed only once

In order to append data to my request object using a middleware, I am looking for a solution that will execute only once the server is up. My attempt at achieving this involved using a middleware along with a function's context, but encountered diffic ...

Utilizing Typescript with Angular 2 to efficiently convert JSON data into objects within HTTP requests

I am dealing with a file called location.json, which contains JSON data structured like this: { "locations": [ { "id": 1, "places": [ { "id": 1, "city": "A ...

Ways to verify if TypeScript declaration files successfully compile with local JavaScript library

I have recently updated the typescript definitions in HunterLarco/twitter-v2, which now follows this structure: package.json src/ twitter.js twitter.d.ts Credentials.js Credentials.d.ts My goal is to verify that the .js files correspond correctly ...

Place a hook following the storage of a variable in the device's memory

Within a component, I am facing the following situation: const [home, setHome]=useState(false) if(home){ return(<Redirect push={true} to="/" />); } setItem("isRegistered", resquest[0].user) setHome(true) The issue here is that ...

The InMemoryCache feature of Apollo quietly discards data associated with fragments that are declared on the main

After sending the following query to my GraphQL server: fragment B on root_query { foo { id } } query A { ...B } The data received from the server includes the foo field. However, when I retrieve it using Apollo's InMemoryCache a ...

What is the best way to output a JSX element using an inline switch statement?

I have been attempting to use an inline switch in order to return an element, but all I am getting is an empty <span> </span>. What could be the issue here? getRowTdForHeader: (header: string, entry: response) => { return (< ...