简体   繁体   中英

How to trace a failed asynchronous test in Jest?

- UPDATE -

The issue has been identified.

In the actual codebase the assertion is passed to a imported callback, and once the callback executes with a failed test, it raises a promise rejection.

So, this is close to how the test was actually written:

describe( "file system", () => {

  it( "should check if the file exists", async () => {

    call( async () => {

      const received = await fileExists();
      const expected = true;

      expect( received ).toBe( expected );

    });
  });
});

and the complex callback is presented in a simpler way to produce the same issue:

export function call( callback) {

  callback();

}

- UPDATE -

The following code works.

I picked up a small portion of the code from a large codebase for better visibility. If I run just the following piece of code, it works as expected. I think there's an issue in the actual codebase.

@Flask's recommendation of handling the unhandled promise rejections centrally added a great value to the question.


Consider the following test:

import fileExists, { call } from "./exists";

describe( "file system", () => {

  it( "should check if the file exists", async () => {

    const received = await fileExists();
    const expected = true;

    expect( received ).toBe( expected );
  });
});

for the following source:

import fs, { constants } from "fs";
import { promisify } from "util";

export default async function fileExists() {

  const path    = ".nonexistent";
  const access  = promisify( fs.access );

  try {

    await access( path, constants.F_OK );

  } catch {

    return false;

  }

  return true;

}

When fileExists rejectsreturns false , an UnhandledPromiseRejectionWarning is received as expected. But this does not help trace the source of the failed test.

For synchronous tests, Jest shows the path to the test (ie file system › should check if the file exists ) which helps trace the source of the failed test.

What is the best way to achieve this for asynchronous tests?

UnhandledPromiseRejectionWarning is not expected here. It's not equivalent to failed test because it doesn't prevent a test to pass if assertions pass. It means that the code was written the wrong way and contains unchained promises.

It can happen only if await was omitted in the test:

fileExists(); // no await

Or fileExists function contains loose unhandled promises:

fileExists() {
  whatever() // no return
  .then(() => {
    whatever() // no return
  })  // no catch to suppress errors
}

It's a good practice to have in setupFiles :

process.on('unhandledRejection', console.error);

It provides more useful output than UnhandledPromiseRejectionWarning and allows to debug the problem based on error stack.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM