407 votes

Pouvez-vous écrire des tests asynchrones qui attendent toThrow ?

J'écris un test asynchrone qui s'attend à ce que la fonction asynchrone soit lancée comme ceci :

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

Mais Jest échoue juste au lieu de passer le test :

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

    Failed: I should fail!

Si je réécris le test pour qu'il ressemble à ceci :

expect(async () => {
  await failingAsyncTest()
}).toThrow()

J'obtiens cette erreur au lieu d'un test réussi :

expect(function).toThrow(undefined)

Expected the function to throw an error.
But it didn't throw anything.

790voto

Lisandro Points 676

Vous pouvez tester votre fonction asynchrone comme ceci :

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

La chaîne "I should fail" correspondra à n'importe quelle partie de l'erreur déclenchée.

25 votes

Ceci est maintenant documenté dans facebook.github.io/jest/docs/en/expect.html#rejects

10 votes

En fait, il y a des problèmes, l'exemple documenté échoue. github.com/facebook/jest/issues/3601 Il existe des solutions de contournement, notamment await expect(failingAsyncTest()).rejects.toHaveProperty('message', 'I should fail');

3 votes

@Lisandro Ce code ne fonctionne pas. Oui, le test unitaire passe, mais pas parce que failingAsyncTest a lancé le bon type d'erreur. C'est plus évident si vous modifiez l'implémentation de la fonction failingAsyncTest à jeter la mauvaise erreur au lieu de la bonne. (en utilisant Jest 23.6)

97voto

Steve Points 31

Je voudrais juste ajouter que la fonction que vous testez doit lancer un objet d'erreur réel. throw new Error(...) . Jest ne semble pas reconnaître si vous lancez simplement une expression comme throw 'An error occurred!' .

34 votes

Vous venez de me faire gagner un temps fou.

2 votes

J'ai également eu ce problème - merci !

1 votes

Y a-t-il une solution de contournement si nous devons garder throw 'an error' ?

44voto

Sumit Bopche Points 126
await expect(async () => { 
    await someAsyncFunction(someParams); 
}).rejects.toThrowError("Some error message");

Nous devons envelopper le code dans une fonction pour attraper l'erreur. Ici, nous nous attendons à ce que le message d'erreur envoyé par someAsyncFunction soit égal à "Some error message". Nous pouvons également appeler le gestionnaire d'exception

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

Lire la suite https://jestjs.io/docs/expect#tothrowerror

22voto

Classe d'erreur personnalisée

L'utilisation de rejects.toThrow ne fonctionnera pas pour vous. Au lieu de cela, vous pouvez combiner les rejects avec la méthode toBeInstanceOf pour correspondre à l'erreur personnalisée qui a été déclenchée.

Exemple

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

o

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

11voto

Jonas Braga Points 11

Pour pouvoir réaliser de nombreuses conditions de test sans devoir résoudre la promesse à chaque fois, cela fonctionnera également :

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'),
            })
        })
    })

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X