如何用玩笑测试 void async 函数是否成功?

How to test if a void async function was successful with jest?

如何用jest简洁地测试void async函数是否执行成功?我正在使用 TypeScript。

// foo.ts
export class Foo {
  public async bar(): Promise<void> {
    await someAsync();
  }
}

如何测试 new Foo().bar() 不抛出错误?

这是我找到的最好的方法。希望有更优雅的东西。

describe("Foo.bar()", () => {
  it("should not throw", async () => {
    expect.assertions(1);

    try {
      await new Foo().bar();
      expect(true).toBeTruthy();
    } catch {
      // should not come here
    }
  });
});

...替代方案是 resolves 断言。

describe("Foo.bar()", () => {
  it("should not throw", () => {
      return expect(new Foo().bar()).resolves.toEqual();
  });
});

这里你必须 return 结果,因为它是一个 Promise(开玩笑等到它实现)。如果您只需要验证已解决(或被拒绝 - 有类似的道具 rejects 用于检查拒绝值),它会稍微简洁一些。

但如果您需要 运行 在基于 promise 的函数 运行 之后进行多次检查,例如

describe("Foo.bar()", () => {
  it("should not throw", () => {
      const promise = new Foo().bar()
      expect(promise).resolves.toEqual();
      expect(someMock).toHaveBeenCalled();
      return promise;
  });
});

您可能会发现带有 async/await 的选项更……令人满意?

PS 至于你的变体

describe("Foo.bar()", () => {
  it("should not throw", async () => {
    expect.assertions(1);

    try {
      await new Foo().bar();
      expect(true).toBeTruthy();
    } catch {
      // should not come here
    }
  });
});

我认为不需要捕获错误 - 所以 expect.assertions 也变得多余了。为什么?未捕获的异常将使您的测试失败,并且预计不会出现异常,因此它可以失败。如果您期望异常并想检查其属性,则需要这样的结构。

此外,如果带有 expect.assertions 的测试失败选项将通知您失败,而未捕获的异常将突出显示特定语句(如果测试有多个可能出现异常的语句则很有用)

[UPD] 我也错过了最初的一点,你需要检查 promise 是否用 any 结果解决(我的版本检查它用 undefined 解决,但不是非常好的举动(如果函数开始 returning something 如果它 returned nothing 之前它不会破坏任何东西) .同时我们应该至少有一个检查测试...

所以也许您使用存根 expect(true) 的方法在这里是同样合法的。

但如果您不想在同一个测试用例中制作更多 expect,我会验证两次。被测试的语句真的如此孤立吗?或者您只是将相关检查分解为单独的 it()?

这是我发现的最语义化的方式。 甚至只是测试名称的翻译。

describe("Foo.bar()", () => {
      test("Should not throw", async () => {
        await expect(new Foo().bar()).resolves.not.toThrow();
      });
    });

Promise 的优点是它根本不应该抛出,而应该被解决或拒绝。另一方面,toBe() 断言需要一个参数,即使在 TypeScript 中有一个 Promise<void>

那么如果没有传递参数(或者参数为空)但它仍然被评估怎么办。参数是 undefined

  test("Should resolve", async () => {
      await expect(new Foo().bar()).resolves.toBe(undefined);
  });

测试not.toThrow()碰巧是我的假朋友,因为我的Foo.bar()没有抛出,也没有解决。