如何在Jest中跟踪失败的异步测试?

时间:2020-10-15 06:29:58

标签: javascript unit-testing asynchronous promise jestjs

-更新-

已确定问题。

在实际的代码库中,将断言传递给导入的回调,一旦回调以失败的测试执行,则会引发承诺拒绝。

因此,这与测试的实际编写方式很接近:

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

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

    call( async () => {

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

      expect( received ).toBe( expected );

    });
  });
});

并以更简单的方式显示复杂的回调以产生相同的问题:

export function call( callback) {

  callback();

}

-更新-

以下代码有效。

我从大型代码库中提取了一小部分代码,以提高可视性。如果我只运行下面的代码,它将按预期工作。我认为实际的代码库中存在问题。

@Flask关于处理未处理的诺言拒绝的建议为该问题增加了很大的价值。


请考虑以下测试:

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 );
  });
});

适用于以下来源:

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;

}

fileExists 拒绝返回false时,将按预期接收到UnhandledPromiseRejectionWarning 。但这无助于追踪失败测试的根源。

对于同步测试,Jest显示测试的路径(即file system › should check if the file exists),这有助于跟踪失败的测试的来源。

实现异步测试的最佳方法是什么?

1 个答案:

答案 0 :(得分:3)

UnhandledPromiseRejectionWarning在这里不是预期的。它不等于失败的测试,因为它不会阻止断言通过时测试通过。这意味着代码编写方式错误,并且包含未链接的承诺。

只有在测试中省略await时,它才会发生:

fileExists(); // no await

或者fileExists函数包含未处理的宽松承诺:

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

setupFiles中拥有一个好习惯:

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

UnhandledPromiseRejectionWarning相比,它提供了更多有用的输出,并允许基于错误堆栈来调试问题。