你能编写期望toThrow的异步测试吗?

Sea*_*ean 32 jestjs

我正在写一个异步测试,希望async函数像这样抛出:

it("expects to have failed", async () => {
  let getBadResults = async () => {
    await failingAsyncTest()
  }
  expect(await getBadResults()).toThrow()
})
Run Code Online (Sandbox Code Playgroud)

但是,开玩笑只是失败而不是通过测试:

 FAIL  src/failing-test.spec.js
  ? expects to have failed

    Failed: I should fail!
Run Code Online (Sandbox Code Playgroud)

如果我重写测试看起来像这样:

expect(async () => {
  await failingAsyncTest()
}).toThrow()
Run Code Online (Sandbox Code Playgroud)

我收到此错误而不是通过测试:

expect(function).toThrow(undefined)

Expected the function to throw an error.
But it didn't throw anything.
Run Code Online (Sandbox Code Playgroud)

Lis*_*dro 68

您可以像这样测试异步函数:

it('should test async errors', async () =>  {        
    await expect(failingAsyncTest())
    .rejects
    .toThrow('I should fail');
});
Run Code Online (Sandbox Code Playgroud)

'我应该失败'字符串将匹配抛出的错误的任何部分.

  • 实际上有问题,记录的示例失败。https://github.com/facebook/jest/issues/3601 有解决方法,包括`await expect(failingAsyncTest()).rejects.toHaveProperty('message', 'I should fail');` (5认同)
  • 现将其记录在https://facebook.github.io/jest/docs/en/expect.html#rejects中 (4认同)
  • @Tom 解决方案从未声称与错误 **Type** 匹配。它清楚地说明字符串与错误 **Message** 匹配。它工作得很好。最好的事物。 (3认同)
  • @Lisandro 此代码不起作用。是的,单元测试通过了,但不是因为 `failingAsyncTest` 抛出了正确的错误类型。如果您将 `failingAsyncTest` 的实现更改为抛出_错误的错误_而不是正确的错误,则更加明显。(使用 Jest 23.6) (2认同)
  • Expect(promise).rejects.toMatch(error) 和 Expect(promise).rejects.toThrow(error) 之间有什么区别?拒绝不应该解开实际的错误吗?那么,这就没有意义(或者对我来说没有意义)->expect(error).toThrow(error)。这里有一个 toMatch 与拒绝的示例:https://jestjs.io/docs/asynchronous#asyncawait (2认同)

Ste*_*hen 47

我想补充一点,并说您正在测试的函数必须抛出一个实际的 Error object throw new Error(...)。Jest 似乎无法识别您是否只是抛出像throw 'An error occurred!'.

  • 好吧,你刚刚为我节省了很多时间。 (11认同)
  • 我也遇到了这个问题 - 谢谢! (2认同)

小智 47

await expect(async () => { 
    await someAsyncFunction(someParams); 
}).rejects.toThrowError("Some error message");
Run Code Online (Sandbox Code Playgroud)

我们必须将代码包装在函数中以捕获错误。在这里,我们期望从 someAsyncFunction 抛出的错误消息应该等于“Some error message”。我们也可以调用异常处理程序

await expect(async () => { 
    await someAsyncFunction(someParams); 
}).rejects.toThrowError(new InvalidArgumentError("Some error message"));
Run Code Online (Sandbox Code Playgroud)

阅读更多https://jestjs.io/docs/expect#to throwerror

  • 您可以使用“await Expect(someAsyncFunction(someParams)).rejects.toThrowError(...)”更简单地完成此操作。 (4认同)

Lao*_*tih 27

自定义错误类

使用rejects.toThrow对你来说不起作用。相反,您可以将该rejects方法与toBeInstanceOf匹配器结合起来以匹配已引发的自定义错误。

例子

it("should test async errors", async () => {
  await expect(asyncFunctionWithCustomError()).rejects.toBeInstanceOf(
    CustomError
  )
})
Run Code Online (Sandbox Code Playgroud)


小智 14

为了能够制定许​​多测试条件而不必每次都解决承诺,这也将起作用:

it('throws an error when it is not possible to create an user', async () => {
        const throwingFunction = () => createUser(createUserPayload)

        // This is what prevents the test to succeed when the promise is resolved and not rejected
        expect.assertions(3)

        await throwingFunction().catch(error => {
            expect(error).toBeInstanceOf(Error)
            expect(error.message).toMatch(new RegExp('Could not create user'))
            expect(error).toMatchObject({
                details: new RegExp('Invalid payload provided'),
            })
        })
    })
Run Code Online (Sandbox Code Playgroud)


Dmi*_*117 10

如果你想测试异步函数不会抛出:

it('async function does not throw', async () => {
    await expect(hopefullyDoesntThrow()).resolves.not.toThrow();
});
Run Code Online (Sandbox Code Playgroud)

无论返回的值如何,即使未定义,上述测试都会通过。

请记住,如果一个函数抛出一个错误,它实际上会作为 Node 中的Promise Rejectionasync返回,而不是一个错误(这就是为什么如果你没有 try/catch 块,你会得到一个,与错误略有不同)。因此,正如其他人所说,这就是您使用以下任一方法的原因:UnhandledPromiseRejectionWarning

  1. .rejects.resolves方法,或者
  2. try/catch阻止您的测试。

参考: https: //jestjs.io/docs/asynchronous#asyncawait


小智 7

我一直在测试 Firebase 云功能,这就是我得出的结论:

test("It should test async on failing cloud functions calls", async () => {
    await expect(async ()=> {
        await failingCloudFunction(params)
    })
    .rejects
    .toThrow("Invalid type"); // This is the value for my specific error
  });
Run Code Online (Sandbox Code Playgroud)

这是建立在lisandro 的答案之上的。