wake-up-neo.com

Wie kann ich einen Test in Jest nicht bestehen, wenn eine nicht abgefangene Versagensabweisung erfolgt?

Ich arbeite daran, einem Node-Projekt, an dem ich arbeite, Jest zu verwenden, um Test-Coverage hinzuzufügen. Der von mir getestete Code wirft Fehler innerhalb der Versprechungen ab, die dazu führen, dass eine UnhandledPromiseRejectionWarning-Meldung an der Konsole protokolliert wird.

Während ich Tests schreibe, kann ich diese Probleme ziemlich leicht identifizieren und beheben, aber diese Warnungen veranlassen Jest nicht dazu, die Tests als fehlgeschlagen zu markieren, sodass unser CI es nicht fängt. Ich habe nach Vorschlägen gesucht und nicht viel gefunden.

Ich habe in der Dokumentation von Node gefunden, dass Sie diese Warnungen abfangen und damit umgehen können ...

process.on('unhandledRejection', (error) => {
  throw error; // Or whatever you like...
});

Es scheint also ziemlich einfach zu sein, diesen Code in meine Testfälle aufzunehmen. Schließlich sollte eine Error, die innerhalb des Tests geworfen wird, dazu führen, dass der Test fehlschlägt ...

describe('...', () => {
  it('...', () => {
    process.on('uncaughtRejection', (error) => {
      throw error;
    });

    // the rest of my test goes here
  });
});

Leider ist das Verhalten, das ich sehe, dass der Fehler do geworfen wird, aber Jest fängt es nicht auf und scheitert am Test. Stattdessen stürzt Jest mit diesem Fehler ab und die Tests werden nicht weiter ausgeführt. Dies ist nicht wirklich wünschenswert und scheint ein falsches Verhalten zu sein.

Das Aussenden eines Fehlers außerhalb des uncaughtRejection-Handlers funktioniert wie erwartet: Jest protokolliert den ausgelösten Fehler und schlägt den Test fehl, stürzt jedoch nicht ab. (d. h. der Testbeobachter beobachtet und führt Tests durch)

6
Jesse Dunlap

Die Art und Weise, wie ich an diese Herangehensweise herangegangen bin, ist sehr stark an die Art, wie ich meine Funktionen schreibe, gebunden. Grundsätzlich sollte jede Funktion, die Versprechungen verwendet, ein Versprechen bringen. Dies ermöglicht, dass jeder Code, der diese Funktion aufruft, das Abfangen von Fehlern auf eine beliebige Art und Weise behandelt, die es für richtig hält. Beachten Sie, dass dies mein Ansatz ist und ich nicht behaupten kann, dass dies die einzige Möglichkeit ist, Dinge zu tun.

Zum Beispiel ... Stellen Sie sich vor, ich teste diese Funktion:

const myFunction = () => {
    return doSomethingWithAPromise()
        .then(() => {
            console.log('no problems!');
            return true;
        });
};

Der Test sieht ungefähr so ​​aus:

describe('...', () => {
    it('...', () => {
        return myFunction()
            .then((value) => {
                expect(value).toBe(true);
            });
    });
});

Welches funktioniert super. Was passiert nun, wenn das Versprechen abgelehnt wird? In meinem Test wird das abgelehnte Versprechen an Jest zurückgegeben (weil ich das Ergebnis meines Funktionsaufrufs zurücksende) und Jest kann darüber berichten.

Wenn Ihre Funktion stattdessen kein Versprechen zurückgibt, müssen Sie möglicherweise Folgendes tun:

const myOtherFunction = () => {
    doSomethingWithAPromise()
        .then(() => {
            console.log('no problems!');
            return true;
        })
        .catch((err) => {
             // throw the caught error here
             throw err;
        });
};

Im Gegensatz zum obigen Beispiel gibt es für Jest keinen (direkten) Weg, ein abgelehntes Versprechen zu bearbeiten, da Sie das Versprechen nicht an Jest zurückgeben. Eine Möglichkeit, dieses zu vermeiden, könnte sein, um sicherzustellen, dass es eine catch in der Funktion gibt, die den Fehler abfängt, aber ich habe es nicht versucht und bin mir nicht sicher, ob es zuverlässiger wäre.

1
Kryten