167 votes

NodeJS UnhandledPromiseRejectionWarning

Donc, je vais tester un composant qui s'appuie sur un événement de l'émetteur. Pour ce faire, je suis venu avec une solution à l'aide de Promesses avec Moka+Chai:

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
    if (!resolved) {
      reject('Timedout!');
    }
    clearTimeout(timeout);
  }, 100);
}).then(((state) => {
      resolved = true;
      assert(state.action === 'DONE', 'should change state');
      done();
    }))
    .catch((error) => {
      assert.isNotOk(error,'Promise error');
      done();
    });
  });
});

Sur la console, j'obtiens un "UnhandledPromiseRejectionWarning" même si la rejeter fonction est appelé, car il montre instantanément le message "AssertionError: la Promesse d'erreur'

(node:25754) UnhandledPromiseRejectionWarning: non Gérée promesse rejet (rejet de l'id: 2): AssertionError: la Promesse d'erreur: { Objet (message, showDiff, ...) } pour être falsy 1) si la transition avec le bon événement

Et puis, au bout de 2 sec je obtenir

Erreur: délai d'attente de 2000ms dépassé. Assurer la done() rappel est appelé dans ce test.

Ce qui est encore plus étrange depuis la capture de rappel a été exécuté.(Je pense que pour certaines raison de l'affirmer échec empêché le reste de l'exécution)

Maintenant, le plus drôle, si j'en commentaire l' assert.isNotOk(error...) le test se passe bien avec tout d'avertissement dans la console. Il stills "échoue", dans le sens qu'elle exécute l'attraper.
Mais encore, je ne peux pas comprendre ces erreurs avec la promesse. Quelqu'un peut-il m'éclairer?

191voto

robertklep Points 29669

Le problème est causé par ceci:

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

Si l'assertion échoue, il renvoie une erreur. Cette erreur entraîne done() jamais appelé, parce que le code d'erreur avant. Qu'est ce qui cause le délai d'attente.

Le "non Gérée promesse de rejet" est également causée par l'échec de l'assertion, parce que si une erreur est renvoyée dans un catch() gestionnaire, et il n'y a pas une ultérieure catch() gestionnaire, l'erreur sera d'être avalé (comme expliqué dans cet article). L' UnhandledPromiseRejectionWarning d'avertissement est à vous alerter à ce fait.

En général, si vous voulez tester la promesse code de Moka, vous devez compter sur le fait que Moka lui-même peut gérer promet déjà. Vous ne devriez pas utiliser done(), mais au lieu de cela, de retour d'une promesse de votre test. Moka sera alors intercepter les erreurs lui-même.

Comme ceci:

it('should transition with the correct event', () => {
  ...
  return new Promise((resolve, reject) => {
    ...
  }).then((state) => {
    assert(state.action === 'DONE', 'should change state');
  })
  .catch((error) => {
    assert.isNotOk(error,'Promise error');
  });
});

18voto

gsalgadotoledo Points 1165

Pour ceux qui sont à la recherche de l'erreur/avertissement UnhandledPromiseRejectionWarning en dehors d'un environnement de test, Il pourrait être probablement parce que personne, dans le code, c'est prendre soin de l'éventuelle erreur dans une promesse:

Par exemple, ce code va afficher l'avertissement signalé dans cette question:

new Promise((resolve, reject) => {
  return reject('Error reason!');
});

(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!

et l'ajout de l' .catch() ou de la manipulation de l'erreur doit résoudre l'avertissement/erreur

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).catch(() => { /* do whatever you want here */ });

Ou en utilisant le second paramètre dans l' then fonction

new Promise((resolve, reject) => {
  return reject('Error reason!');
}).then(null, () => { /* do whatever you want here */ });

11voto

danday74 Points 15895

J'ai eu cette erreur lors de l'écrasant avec sinon.

La solution est d'utiliser npm paquet sinon comme promis lors de la résolution ou de rejet de promesses avec talons.

Au lieu de ...

sinon.stub(Database, 'connect').returns(Promise.reject( Error('oops') ))

L'utilisation ...

require('sinon-as-promised');
sinon.stub(Database, 'connect').rejects(Error('oops'));

Il y a aussi une méthode résout (notez le s à la fin).

Voir http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections

11voto

Matthew Orlando Points 319

L'affirmation bibliothèques Moka le travail en lançant un message d'erreur si l'affirmation n'était pas correcte. Jeter une erreur se produit dans le refus de la promesse, même lorsqu'elles sont rejetées dans l'exécuteur de la fonction prévue à l' catch méthode.

.catch((error) => {
  assert.isNotOk(error,'Promise error');
  done();
});

Dans le code ci-dessus l' error opposés évalue true donc l'affirmation de la bibliothèque renvoie une erreur... qui n'est jamais pris. Comme un résultat de l'erreur de l' done méthode n'est jamais appelé. Moka est done rappel accepte de ces erreurs, alors vous pouvez tout simplement fin à toute promesse de chaînes de Moka avec .then(done,done). Cela garantit que la méthode est toujours appelé et l'erreur doit être signalé de la même manière que lorsque Moka captures de l'affirmation de l'erreur dans le code synchrone.

it('should transition with the correct event', (done) => {
  const cFSM = new CharacterFSM({}, emitter, transitions);
  let timeout = null;
  let resolved = false;
  new Promise((resolve, reject) => {
    emitter.once('action', resolve);
    emitter.emit('done', {});
    timeout = setTimeout(() => {
      if (!resolved) {
        reject('Timedout!');
      }
      clearTimeout(timeout);
    }, 100);
  }).then(((state) => {
    resolved = true;
    assert(state.action === 'DONE', 'should change state');
  })).then(done,done);
});

Je donne crédit à cet article pour l'idée de l'aide .ensuite(en fait,en fait) lors de l'essai de promesses de Moka.

1voto

Fronker Points 658

Voici mon prendre de l'expérience avec E7 async/await:

Dans le cas où vous avez un async helperFunction() appelés à partir de votre test... (un explicilty avec l'ES7 async mot-clé, je veux dire)

→ assurez-vous, vous appelez ça comme await helperFunction(whateverParams) (eh bien, oui, naturellement, une fois que vous savez...)

Et pour que cela fonctionne (à éviter l ‘ " attendre est un mot réservé), votre test de fonction doit avoir un extérieur async marqueur:

it('my test', async () => { ...

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