Ich teste also eine Komponente, die auf einem Ereignisemitter basiert. Zu diesem Zweck habe ich mit Promises with Mocha + Chai eine Lösung gefunden:
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();
});
});
Auf der Konsole wird "UnhandledPromiseRejectionWarning" angezeigt, obwohl die Ablehnungsfunktion aufgerufen wird, da sofort die Meldung "AssertionError: Promise error" angezeigt wird.
(Knoten: 25754) UnhandledPromiseRejectionWarning: Nicht behandelte Ablehnung von Versprechungen (Ablehnungs-ID: 2): AssertionError: Versprechungsfehler: Es wird erwartet, dass {Objekt (Nachricht, showDiff, ...)} mit dem richtigen Ereignis übergeht
Und dann, nach 2 Sekunden bekomme ich
Fehler: Zeitüberschreitung von 2000 ms überschritten. Stellen Sie sicher, dass der Rückruf done () in diesem Test aufgerufen wird.
Was noch seltsamer ist, seit der Catch-Callback ausgeführt wurde (ich denke, dass aus irgendeinem Grund der Assert-Fehler den Rest der Ausführung verhindert hat).
Nun das Lustige, wenn ich das auskommentiere, assert.isNotOk(error...)
läuft der Test ohne Warnung in der Konsole einwandfrei. Es schlägt immer noch in dem Sinne fehl, dass es den Fang ausführt.
Trotzdem kann ich diese Fehler nicht mit Versprechen verstehen. Kann mich jemand aufklären?
Antworten:
Das Problem wird dadurch verursacht:
Wenn die Zusicherung fehlschlägt, wird ein Fehler ausgegeben. Dieser Fehler führt dazu, dass er
done()
niemals aufgerufen wird, da der Code zuvor fehlerhaft war. Das ist es, was das Timeout verursacht.Die "Ablehnung eines nicht behandelten Versprechens" wird auch durch die fehlgeschlagene Behauptung verursacht. Wenn ein Fehler in einem
catch()
Handler ausgelöst wird und kein nachfolgendercatch()
Handler vorhanden ist , wird der Fehler verschluckt (wie in diesem Artikel erläutert ). DieUnhandledPromiseRejectionWarning
Warnung macht Sie auf diese Tatsache aufmerksam.Wenn Sie versprechungsbasierten Code in Mocha testen möchten, sollten Sie sich im Allgemeinen darauf verlassen, dass Mocha selbst bereits Versprechungen verarbeiten kann. Sie sollten nicht verwenden
done()
, sondern ein Versprechen von Ihrem Test zurückgeben. Mokka erkennt dann alle Fehler selbst.So was:
quelle
catch
Handler sollte wahrscheinlich als zweites Argument an übergeben werdenthen
. Ich bin mir jedoch nicht ganz sicher, was die Absicht des OP war, also habe ich es so belassen, wie es ist.done.fail('msg')
in diesem Fall.Ich habe diesen Fehler beim Stubben mit Sinon erhalten.
Die Lösung besteht darin, das versprochene npm-Paket sinon zu verwenden , wenn Versprechen mit Stubs gelöst oder abgelehnt werden.
Anstatt ...
Verwenden ...
Es gibt auch eine Auflösungsmethode (beachten Sie das s am Ende).
Siehe http://clarkdave.net/2016/09/node-v6-6-and-asynchronously-handled-promise-rejections
quelle
Die Assertionsbibliotheken in Mocha geben einen Fehler aus, wenn die Assertion nicht korrekt war. Das Auslösen eines Fehlers führt zu einem abgelehnten Versprechen, selbst wenn die für die
catch
Methode bereitgestellte Executor-Funktion ausgelöst wird.Im obigen Code
error
wertet das Objekt aus,true
sodass die Assertionsbibliothek einen Fehler auslöst ... der niemals abgefangen wird. Aufgrund des Fehlers wird diedone
Methode niemals aufgerufen. Mochasdone
Rückruf akzeptiert diese Fehler, sodass Sie einfach alle Versprechensketten in Mocha mit beenden können.then(done,done)
. Dies stellt sicher, dass die Methode done immer aufgerufen wird und der Fehler auf dieselbe Weise gemeldet wird, wie wenn Mocha den Fehler der Zusicherung im synchronen Code abfängt.Ich gebe diesem Artikel Anerkennung für die Idee, .then (erledigt, erledigt) beim Testen von Versprechungen in Mokka zu verwenden.
quelle
Für diejenigen, die
UnhandledPromiseRejectionWarning
außerhalb einer Testumgebung nach dem Fehler / der Warnung suchen , könnte dies wahrscheinlich daran liegen, dass sich niemand im Code um den eventuellen Fehler in einem Versprechen kümmert:In diesem Code wird beispielsweise die in dieser Frage gemeldete Warnung angezeigt:
(node:XXXX) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Error reason!
Das Hinzufügen
.catch()
oder Behandeln des Fehlers sollte die Warnung / den Fehler behebenOder verwenden Sie den zweiten Parameter in der
then
Funktionquelle
new Promise((resolve, reject) => { return reject('Error reason!'); })
sondern in der Funktion,function test() { return new Promise((resolve, reject) => { return reject('Error reason!'); });}
sodass wir innerhalb der Funktion keine verwenden müssen,.catch()
aber um Fehler erfolgreich zu behandeln, reicht es aus, diese Funktion aufzurufentest().catch(e => console.log(e))
oder die asynchrone /try { await test() } catch (e) { console.log(e) }
Ich stand vor diesem Problem:
Es war mein Fehler, ich habe das
res
Objekt ersetztthen(function(res)
, alsores
in Ergebnis geändert und jetzt funktioniert es.Falsch
Korrektur
Service code:
quelle
Hier ist meine Erfahrung mit E7 async / await :
Falls Sie
async helperFunction()
einen Anruf von Ihrem Test haben ... (eine Erklärung mit dem ES7-async
Schlüsselwort, meine ich)→ stellen Sie sicher, dass Sie das so nennen
await helperFunction(whateverParams)
(na ja, natürlich, sobald Sie es wissen ...)Und damit dies funktioniert (um zu vermeiden, dass Warten ein reserviertes Wort ist), muss Ihre Testfunktion einen äußeren asynchronen Marker haben:
quelle
await helperFunction(...)
. Eineasync
Funktion gibt ein Versprechen zurück. Sie können das zurückgegebene Versprechen einfach so behandeln, wie Sie es bei einer nicht markierten Funktion tun würdenasync
, die zufällig ein Versprechen zurückgibt. Es geht darum, das Versprechen zu erfüllen, Punkt. Ob die Funktion istasync
oder nicht, spielt keine Rolle.await
ist nur eine von mehreren Möglichkeiten, mit dem Versprechen umzugehen.UnhandledPromiseRejectionWarning
für mich verursacht hat ... also diese Antwort.Ich hatte eine ähnliche Erfahrung mit Chai-Webdriver für Selen. Ich
await
habe der Behauptung hinzugefügt und das Problem behoben:Beispiel mit Cucumberjs:
quelle
Ich habe dieses Problem nach der Deinstallation von Webpack gelöst (reagieren Sie auf das Problem).
quelle