Hopp til hovedinnhold
Versjon: 30.0

Testing Asynchronous Code

Unofficial Beta Translation

This page was AI-translated by PageTurner (beta). Not officially endorsed by the project. Found an error? Report issue →

Det er vanlig i JavaScript at kode kjører asynkront. Når du har asynkron kode, må Jest vite når koden den tester er ferdig utført før den kan gå videre til neste test. Jest har flere måter å håndtere dette på.

Promises

Returner et promise fra testen din, så venter Jest til dette promiset er løst. Hvis promiset avvises, vil testen feile.

La oss si at fetchData returnerer et promise som skal løses til strengen 'peanut butter'. Vi kan teste det med:

test('the data is peanut butter', () => {
return fetchData().then(data => {
expect(data).toBe('peanut butter');
});
});

Async/Await

Du kan også bruke async og await i testene dine. For å skrive en asynkron test, bruk async-nøkkelordet foran funksjonen du sender til test. For eksempel kan det samme fetchData-scenariet testes med:

test('the data is peanut butter', async () => {
const data = await fetchData();
expect(data).toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
expect.assertions(1);
try {
await fetchData();
} catch (error) {
expect(error).toMatch('error');
}
});

Du kan kombinere async og await med .resolves eller .rejects.

test('the data is peanut butter', async () => {
await expect(fetchData()).resolves.toBe('peanut butter');
});

test('the fetch fails with an error', async () => {
await expect(fetchData()).rejects.toMatch('error');
});

I disse tilfellene er async og await essensielt syntaktisk sukker for samme logikk som promise-eksemplet bruker.

advarsel

Husk å returnere (eller awaite) promiset - hvis du utelater return/await, vil testen fullføres før promiset fra fetchData er løst eller avvist.

Hvis du forventer at et promise skal avvises, bruk .catch-metoden. Pass på å inkludere expect.assertions for å verifisere at et visst antall assertions blir kalt. Ellers vil et oppfylt promise ikke føre til feil i testen.

test('the fetch fails with an error', () => {
expect.assertions(1);
return fetchData().catch(error => expect(error).toMatch('error'));
});

Callbacks

Hvis du ikke bruker promises, kan du bruke callbacks. La oss si at fetchData i stedet for å returnere et promise forventer en callback, altså henter data og kaller callback(null, data) når den er ferdig. Du vil teste at disse dataene er strengen 'peanut butter'.

Som standard fullføres Jest-tester når de når slutten av utførelsen. Det betyr at denne testen ikke vil fungere som tiltenkt:

// Don't do this!
test('the data is peanut butter', () => {
function callback(error, data) {
if (error) {
throw error;
}
expect(data).toBe('peanut butter');
}

fetchData(callback);
});

Problemet er at testen vil fullføres så snart fetchData er ferdig, før callbacken blir kalt.

Det finnes en alternativ form for test som løser dette. I stedet for å putte testen i en funksjon uten argumenter, bruk et enkelt argument kalt done. Jest vil vente til done-callbacken blir kalt før den avslutter testen.

test('the data is peanut butter', done => {
function callback(error, data) {
if (error) {
done(error);
return;
}
try {
expect(data).toBe('peanut butter');
done();
} catch (error) {
done(error);
}
}

fetchData(callback);
});

Hvis done() aldri blir kalt, vil testen feile (med timeout-feil), som er det du ønsker skal skje.

Hvis expect-setningen feiler, kastes en feil og done() blir ikke kalt. For å se i testloggen hvorfor den feilet, må vi pakke expect i en try-blokk og sende feilen i catch-blokken til done. Ellers får vi en uklar timeout-feil som ikke viser hvilken verdi expect(data) mottok.

advarsel

Jest vil kaste en feil hvis samme testfunksjon får en done()-callback og returnerer et promise. Dette er en forholdsregel for å unngå minnelekkasjer i testene dine.

.resolves / .rejects

Du kan også bruke .resolves-matcheren i expect-setningen din. Jest vil da vente på at promiset skal løses. Hvis promiset avvises, vil testen automatisk feile.

test('the data is peanut butter', () => {
return expect(fetchData()).resolves.toBe('peanut butter');
});

Husk å returnere assertionen – hvis du utelater denne return-setningen, vil testen fullføres før promiset fra fetchData er løst og then() får sjansen til å utføre callbacken.

Hvis du forventer at et promise skal avvises, bruk .rejects-matcheren. Den fungerer analogt med .resolves-matcheren. Hvis promiset oppfylles, vil testen automatisk feile.

test('the fetch fails with an error', () => {
return expect(fetchData()).rejects.toMatch('error');
});

Ingen av disse tilnærmingene er spesielt overlegne de andre, og du kan fritt kombinere dem i et kodebase eller til og med i én enkelt fil. Det avhenger helt av hvilken stil du føler gjør testene dine enklere.