Hopp til hovedinnhold
Versjon: 30.0

Forvent

Unofficial Beta Translation

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

Når du skriver tester, trenger du ofte å sjekke at verdier oppfyller visse betingelser. expect gir deg tilgang til en rekke "matchers" som lar deg validere forskjellige ting.

tips

For flere Jest-matchers vedlikeholdt av Jest-samfunnet, sjekk ut jest-extended.

Unofficial Beta Translation

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

info

TypeScript-eksemplene på denne siden vil bare fungere som dokumentert hvis du eksplisitt importerer Jest API-ene:

import {expect, jest, test} from '@jest/globals';

Se Komme i gang-guiden for detaljer om hvordan du konfigurerer Jest med TypeScript.

Referanse


Forvent

expect(value)

expect-funksjonen brukes hver gang du vil teste en verdi. Du vil sjelden kalle expect alene. I stedet bruker du expect sammen med en "matcher"-funksjon for å bekrefte noe om en verdi.

Det er enklere å forstå dette med et eksempel. La oss si du har en metode bestLaCroixFlavor() som skal returnere strengen 'grapefruit'. Slik ville du testet det:

test('the best flavor is grapefruit', () => {
expect(bestLaCroixFlavor()).toBe('grapefruit');
});

I dette tilfellet er toBe matcher-funksjonen. Det finnes mange ulike matcher-funksjoner, dokumentert nedenfor, som hjelper deg å teste forskjellige ting.

Argumentet til expect bør være verdien koden din produserer, og argumentet til matcheren bør være den korrekte verdien. Hvis du bytter om på dem, vil testene dine fortsatt fungere, men feilmeldingene ved feilede tester vil se merkelige ut.

Modifikatorer

.not

Hvis du vet hvordan du tester noe, lar .not deg teste det motsatte. For eksempel tester denne koden at den beste La Croix-smaken ikke er kokos:

test('the best flavor is not coconut', () => {
expect(bestLaCroixFlavor()).not.toBe('coconut');
});

.resolves

Bruk resolves for å pakke ut verdien av en oppfylt promise slik at enhver annen matcher kan kjøres i kjede. Hvis promisen avvises, feiler påstanden.

For eksempel tester denne koden at promisen resolver og at den resulterende verdien er 'lemon':

test('resolves to lemon', () => {
// make sure to add a return statement
return expect(Promise.resolve('lemon')).resolves.toBe('lemon');
});
notat

Siden du fortsatt tester promises, er testen fortsatt asynkron. Derfor må du be Jest vente ved å returnere den utpakkede påstanden.

Alternativt kan du bruke async/await i kombinasjon med .resolves:

test('resolves to lemon', async () => {
await expect(Promise.resolve('lemon')).resolves.toBe('lemon');
await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus');
});

.rejects

Bruk .rejects for å pakke ut årsaken til en avvist promise slik at enhver annen matcher kan kjøres i kjede. Hvis promisen oppfylles, feiler påstanden.

For eksempel tester denne koden at promisen avvises med årsak 'octopus':

test('rejects to octopus', () => {
// make sure to add a return statement
return expect(Promise.reject(new Error('octopus'))).rejects.toThrow(
'octopus',
);
});
notat

Siden du fortsatt tester promises, er testen fortsatt asynkron. Derfor må du be Jest vente ved å returnere den utpakkede påstanden.

Alternativt kan du bruke async/await i kombinasjon med .rejects.

test('rejects to octopus', async () => {
await expect(Promise.reject(new Error('octopus'))).rejects.toThrow('octopus');
});

Matchers

.toBe(value)

Bruk .toBe til å sammenligne primitive verdier eller for å sjekke referanseidentitet til objektinstanser. Den bruker Object.is for å sammenligne verdier, som er enda bedre for testing enn === (streng likhetsoperator).

For eksempel vil denne koden validere noen egenskaper ved can-objektet:

const can = {
name: 'pamplemousse',
ounces: 12,
};

describe('the can', () => {
test('has 12 ounces', () => {
expect(can.ounces).toBe(12);
});

test('has a sophisticated name', () => {
expect(can.name).toBe('pamplemousse');
});
});

Ikke bruk .toBe med flyttall. For eksempel, på grunn av avrunding er 0.2 + 0.1 i JavaScript ikke strengt lik 0.3. Hvis du har flyttall, bruk .toBeCloseTo i stedet.

Selv om .toBe-matcheren sjekker referanseidentitet, vil den rapportere en dyp sammenligning av verdier hvis påstanden feiler. Hvis forskjeller mellom egenskaper ikke hjelper deg å forstå hvorfor en test feiler, spesielt hvis rapporten er stor, kan du flytte sammenligningen inn i expect-funksjonen. For eksempel, for å bekrefte om elementer er samme instans eller ikke:

  • skriv om expect(received).toBe(expected) til expect(Object.is(received, expected)).toBe(true)

  • skriv om expect(received).not.toBe(expected) til expect(Object.is(received, expected)).toBe(false)

.toHaveBeenCalled()

Bruk .toHaveBeenCalled for å sikre at en mock-funksjon ble kalt.

For eksempel, la oss si du har en drinkAll(drink, flavour)-funksjon som tar en drink-funksjon og bruker den på alle tilgjengelige drikker. Du vil kanskje sjekke at drink blir kalt. Du kan gjøre det med dette testsettet:

function drinkAll(callback, flavour) {
if (flavour !== 'octopus') {
callback(flavour);
}
}

describe('drinkAll', () => {
test('drinks something lemon-flavoured', () => {
const drink = jest.fn();
drinkAll(drink, 'lemon');
expect(drink).toHaveBeenCalled();
});

test('does not drink something octopus-flavoured', () => {
const drink = jest.fn();
drinkAll(drink, 'octopus');
expect(drink).not.toHaveBeenCalled();
});
});

.toHaveBeenCalledTimes(number)

Bruk .toHaveBeenCalledTimes for å sikre at en mock-funksjon ble kalt eksakt antall ganger.

For eksempel, la oss si du har en drinkEach(drink, Array<flavor>)-funksjon som tar en drink-funksjon og bruker den på en liste med drikker. Du vil kanskje sjekke at drink-funksjonen ble kalt eksakt antall ganger. Du kan gjøre det med dette testsettet:

test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenCalledTimes(2);
});

.toHaveBeenCalledWith(arg1, arg2, ...)

Bruk .toHaveBeenCalledWith for å sikre at en mock-funksjon ble kalt med spesifikke argumenter. Argumentene sjekkes med samme algoritme som .toEqual bruker.

For eksempel, la oss si du kan registrere en drikke med en register-funksjon, og applyToAll(f) skal bruke funksjonen f på alle registrerte drikker. For å sikre at dette fungerer, kan du skrive:

test('registration applies correctly to orange La Croix', () => {
const beverage = new LaCroix('orange');
register(beverage);
const f = jest.fn();
applyToAll(f);
expect(f).toHaveBeenCalledWith(beverage);
});

.toHaveBeenLastCalledWith(arg1, arg2, ...)

Hvis du har en mock-funksjon, kan du bruke .toHaveBeenLastCalledWith for å teste hvilke argumenter den ble kalt med sist. For eksempel, la oss si du har en applyToAllFlavors(f)-funksjon som bruker f på mange smaker, og du vil sikre at når du kaller den, er den siste smaken den opererer på 'mango'. Du kan skrive:

test('applying to all flavors does mango last', () => {
const drink = jest.fn();
applyToAllFlavors(drink);
expect(drink).toHaveBeenLastCalledWith('mango');
});

.toHaveBeenNthCalledWith(nthCall, arg1, arg2, ....)

Hvis du har en mock-funksjon, kan du bruke .toHaveBeenNthCalledWith for å teste hvilke argumenter den ble kalt med ved n-te anrop. For eksempel, la oss si du har en drinkEach(drink, Array<flavor>)-funksjon som bruker f på mange smaker, og du vil sikre at når du kaller den, er den første smaken 'lemon' og den andre 'octopus'. Du kan skrive:

test('drinkEach drinks each drink', () => {
const drink = jest.fn();
drinkEach(drink, ['lemon', 'octopus']);
expect(drink).toHaveBeenNthCalledWith(1, 'lemon');
expect(drink).toHaveBeenNthCalledWith(2, 'octopus');
});
notat

n-argumentet må være et positivt heltall som starter fra 1.

.toHaveReturned()

Hvis du har en mock-funksjon, kan du bruke .toHaveReturned for å teste at mock-funksjonen returnerte vellykket (dvs. ikke kastet en feil) minst én gang. For eksempel, la oss si du har en mock drink som returnerer true. Du kan skrive:

test('drinks returns', () => {
const drink = jest.fn(() => true);

drink();

expect(drink).toHaveReturned();
});

.toHaveReturnedTimes(number)

Bruk .toHaveReturnedTimes for å sikre at en mock-funksjon returnerte vellykket (dvs. ikke kastet en feil) et eksakt antall ganger. Anrop til mock-funksjonen som kaster en feil teller ikke med i antallet vellykkede returer.

For eksempel, la oss si du har en mock drink som returnerer true. Du kan skrive:

test('drink returns twice', () => {
const drink = jest.fn(() => true);

drink();
drink();

expect(drink).toHaveReturnedTimes(2);
});

.toHaveReturnedWith(value)

Bruk .toHaveReturnedWith for å sikre at en mock-funksjon returnerte en spesifikk verdi.

For eksempel, la oss si at du har en mock-funksjon drink som returnerer navnet på drikken som ble konsumert. Du kan skrive:

test('drink returns La Croix', () => {
const beverage = {name: 'La Croix'};
const drink = jest.fn(beverage => beverage.name);

drink(beverage);

expect(drink).toHaveReturnedWith('La Croix');
});

.toHaveLastReturnedWith(value)

Bruk .toHaveLastReturnedWith for å teste hvilken spesifikke verdi en mock-funksjon sist returnerte. Hvis det siste kallet til mock-funksjonen kastet en feil, vil denne matcheren feile uansett hvilken verdi du angav som forventet returverdi.

For eksempel, la oss si at du har en mock-funksjon drink som returnerer navnet på drikken som ble konsumert. Du kan skrive:

test('drink returns La Croix (Orange) last', () => {
const beverage1 = {name: 'La Croix (Lemon)'};
const beverage2 = {name: 'La Croix (Orange)'};
const drink = jest.fn(beverage => beverage.name);

drink(beverage1);
drink(beverage2);

expect(drink).toHaveLastReturnedWith('La Croix (Orange)');
});

.toHaveNthReturnedWith(nthCall, value)

Bruk .toHaveNthReturnedWith for å teste hvilken spesifikke verdi en mock-funksjon returnerte for det n-te kallet. Hvis det n-te kallet til mock-funksjonen kastet en feil, vil denne matcheren feile uansett hvilken verdi du angav som forventet returverdi.

For eksempel, la oss si at du har en mock-funksjon drink som returnerer navnet på drikken som ble konsumert. Du kan skrive:

test('drink returns expected nth calls', () => {
const beverage1 = {name: 'La Croix (Lemon)'};
const beverage2 = {name: 'La Croix (Orange)'};
const drink = jest.fn(beverage => beverage.name);

drink(beverage1);
drink(beverage2);

expect(drink).toHaveNthReturnedWith(1, 'La Croix (Lemon)');
expect(drink).toHaveNthReturnedWith(2, 'La Croix (Orange)');
});
notat

n-argumentet må være et positivt heltall som starter fra 1.

.toHaveLength(number)

Bruk .toHaveLength for å kontrollere at et objekt har en .length-egenskap med en spesifikk numerisk verdi.

Dette er spesielt nyttig for å sjekke størrelsen på arrays eller strenger.

expect([1, 2, 3]).toHaveLength(3);
expect('abc').toHaveLength(3);
expect('').not.toHaveLength(5);

.toHaveProperty(keyPath, value?)

Bruk .toHaveProperty for å sjekke om en egenskap på angitt keyPath finnes for et objekt. For dypnestede egenskaper kan du bruke dot-notasjon eller en array med nøkkelstien for dype referanser.

Du kan angi et valgfritt value-argument for å sammenligne den mottatte egenskapsverdien (rekursivt for alle egenskaper, også kjent som deep equality, lik toEqual-matcheren).

Følgende eksempel inneholder et houseForSale-objekt med nestede egenskaper. Vi bruker toHaveProperty for å sjekke eksistensen og verdiene til ulike egenskaper i objektet.

// Object containing house features to be tested
const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
'nice.oven': true,
},
livingroom: {
amenities: [
{
couch: [
['large', {dimensions: [20, 20]}],
['small', {dimensions: [10, 10]}],
],
},
],
},
'ceiling.height': 2,
};

test('this house has my desired features', () => {
// Example Referencing
expect(houseForSale).toHaveProperty('bath');
expect(houseForSale).toHaveProperty('bedrooms', 4);

expect(houseForSale).not.toHaveProperty('pool');

// Deep referencing using dot notation
expect(houseForSale).toHaveProperty('kitchen.area', 20);
expect(houseForSale).toHaveProperty('kitchen.amenities', [
'oven',
'stove',
'washer',
]);

expect(houseForSale).not.toHaveProperty('kitchen.open');

// Deep referencing using an array containing the keyPath
expect(houseForSale).toHaveProperty(['kitchen', 'area'], 20);
expect(houseForSale).toHaveProperty(
['kitchen', 'amenities'],
['oven', 'stove', 'washer'],
);
expect(houseForSale).toHaveProperty(['kitchen', 'amenities', 0], 'oven');
expect(houseForSale).toHaveProperty(
'livingroom.amenities[0].couch[0][1].dimensions[0]',
20,
);
expect(houseForSale).toHaveProperty(['kitchen', 'nice.oven']);
expect(houseForSale).not.toHaveProperty(['kitchen', 'open']);

// Referencing keys with dot in the key itself
expect(houseForSale).toHaveProperty(['ceiling.height'], 'tall');
});

.toBeCloseTo(number, numDigits?)

Bruk toBeCloseTo for å sammenligne flyttall for omtrentlig likhet.

Det valgfrie numDigits-argumentet begrenser antall sifre som sjekkes etter desimalpunktet. Med standardverdi 2 er testkriteriet Math.abs(expected - received) < 0.005 (altså 10 ** -2 / 2).

Intuitive likhetssammenligninger feiler ofte fordi desimalregning (base 10) ofte gir avrundingsfeil i binær (base 2) representasjon med begrenset presisjon. For eksempel feiler denne testen:

test('adding works sanely with decimals', () => {
expect(0.2 + 0.1).toBe(0.3); // Fails!
});

Den feiler fordi i JavaScript er 0.2 + 0.1 faktisk 0.30000000000000004.

For eksempel består denne testen med en presisjon på 5 sifre:

test('adding works sanely with decimals', () => {
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
});

Siden toBeCloseTo løser problemet med flyttallsfeil, støtter den ikke store heltallsverdier.

.toBeDefined()

Bruk .toBeDefined for å kontrollere at en variabel ikke er undefined. For eksempel, hvis du vil sjekke at en funksjon fetchNewFlavorIdea() returnerer noe, kan du skrive:

test('there is a new flavor idea', () => {
expect(fetchNewFlavorIdea()).toBeDefined();
});

Du kunne skrevet expect(fetchNewFlavorIdea()).not.toBe(undefined), men det er bedre praksis å unngå å referere direkte til undefined i koden din.

.toBeFalsy()

Bruk .toBeFalsy når du ikke bryr deg om hva en verdi er, men bare vil forsikre deg om at den evalueres til usann i en boolsk kontekst. For eksempel, la oss si at du har applikasjonskode som ser slik ut:

drinkSomeLaCroix();
if (!getErrors()) {
drinkMoreLaCroix();
}

Du bryr deg kanskje ikke spesifikt om hva getErrors returnerer – den kan returnere false, null eller 0, og koden din vil fortsatt fungere. Så hvis du vil teste at det ikke oppstår feil etter å ha drukket litt La Croix, kan du skrive:

test('drinking La Croix does not lead to errors', () => {
drinkSomeLaCroix();
expect(getErrors()).toBeFalsy();
});

I JavaScript finnes det seks falske verdier: false, 0, '', null, undefined og NaN. Alt annet regnes som sant.

.toBeGreaterThan(number | bigint)

Bruk toBeGreaterThan for å sammenligne received > expected med tall eller store heltallsverdier. For eksempel, test at ouncesPerCan() returnerer en verdi større enn 10 unser:

test('ounces per can is more than 10', () => {
expect(ouncesPerCan()).toBeGreaterThan(10);
});

.toBeGreaterThanOrEqual(number | bigint)

Bruk toBeGreaterThanOrEqual for å sammenligne received >= expected med tall eller store heltallsverdier. For eksempel, test at ouncesPerCan() returnerer minst 12 unser:

test('ounces per can is at least 12', () => {
expect(ouncesPerCan()).toBeGreaterThanOrEqual(12);
});

.toBeLessThan(number | bigint)

Bruk toBeLessThan for å sammenligne received < expected med tall eller store heltallsverdier. For eksempel, test at ouncesPerCan() returnerer mindre enn 20 unser:

test('ounces per can is less than 20', () => {
expect(ouncesPerCan()).toBeLessThan(20);
});

.toBeLessThanOrEqual(number | bigint)

Bruk toBeLessThanOrEqual for å sammenligne received <= expected med tall eller store heltallsverdier. For eksempel, test at ouncesPerCan() returnerer maksimalt 12 unser:

test('ounces per can is at most 12', () => {
expect(ouncesPerCan()).toBeLessThanOrEqual(12);
});

.toBeInstanceOf(Class)

Bruk .toBeInstanceOf(Class) for å verifisere at et objekt er en instans av en klasse. Denne matcheren bruker instanceof under panseret.

class A {}

expect(new A()).toBeInstanceOf(A);
expect(() => {}).toBeInstanceOf(Function);
expect(new A()).toBeInstanceOf(Function); // throws

.toBeNull()

.toBeNull() gir samme resultat som .toBe(null), men med mer forståelige feilmeldinger. Bruk .toBeNull() når du skal sjekke at noe er null.

function bloop() {
return null;
}

test('bloop returns null', () => {
expect(bloop()).toBeNull();
});

.toBeTruthy()

Bruk .toBeTruthy når du ikke bryr deg om den eksakte verdien, men vil forsikre deg om at verdien evalueres til sant i en boolsk kontekst. For eksempel, tenk deg applikasjonskode som dette:

drinkSomeLaCroix();
if (thirstInfo()) {
drinkMoreLaCroix();
}

Du bryr deg kanskje ikke om nøyaktig hva thirstInfo returnerer – den kan returnere true eller et komplekst objekt uten at koden brytes. Hvis du vil teste at thirstInfo gir en sann verdi etter å ha drukket La Croix, kan du skrive:

test('drinking La Croix leads to having thirst info', () => {
drinkSomeLaCroix();
expect(thirstInfo()).toBeTruthy();
});

I JavaScript finnes det seks falske verdier: false, 0, '', null, undefined og NaN. Alt annet regnes som sant.

.toBeUndefined()

Bruk .toBeUndefined for å sjekke at en variabel er udefinert. For eksempel, hvis du vil verifisere at funksjonen bestDrinkForFlavor(flavor) returnerer undefined for smaken 'octopus' (fordi det ikke finnes noen god drikke med blekksprutsmak):

test('the best drink for octopus flavor is undefined', () => {
expect(bestDrinkForFlavor('octopus')).toBeUndefined();
});

Du kunne skrevet expect(bestDrinkForFlavor('octopus')).toBe(undefined), men det anbefales å unngå direkte referanser til undefined i koden.

.toBeNaN()

Bruk .toBeNaN når du skal sjekke om en verdi er NaN.

test('passes when value is NaN', () => {
expect(NaN).toBeNaN();
expect(1).not.toBeNaN();
});

.toContain(item)

Bruk .toContain for å sjekke om et element finnes i en array. Ved testing av array-elementer brukes === (streng likhet). .toContain kan også sjekke om en streng er en delstreng av en annen streng.

For eksempel, hvis getAllFlavors() returnerer en array med smaker og du vil være sikker på at lime er inkludert:

test('the flavor list contains lime', () => {
expect(getAllFlavors()).toContain('lime');
});

Denne matcheren støtter også andre iterable objekter som strenger, mengder (sets), nodelister og HTML-samlinger.

.toContainEqual(item)

Bruk .toContainEqual når du ønsker å sjekke at et element med en spesifikk struktur og verdier finnes i en array. For å teste elementene i arrayen, sjekker denne matcheren rekursivt likheten for alle felter, i stedet for å sjekke objektidentitet.

describe('my beverage', () => {
test('is delicious and not sour', () => {
const myBeverage = {delicious: true, sour: false};
expect(myBeverages()).toContainEqual(myBeverage);
});
});

.toEqual(value)

Bruk .toEqual for å sammenligne alle egenskaper rekursivt i objekter (også kjent som "dyp" likhet). Den bruker Object.is for å sammenligne primitive verdier, som er enda bedre for testing enn den strenge likhetsoperatoren ===.

For eksempel oppfører .toEqual og .toBe seg forskjellig i dette testsettet, så alle testene består:

const can1 = {
flavor: 'grapefruit',
ounces: 12,
};
const can2 = {
flavor: 'grapefruit',
ounces: 12,
};

describe('the La Croix cans on my desk', () => {
test('have all the same properties', () => {
expect(can1).toEqual(can2);
});
test('are not the exact same can', () => {
expect(can1).not.toBe(can2);
});
});
tips

toEqual ignorerer objektnøkler med undefined-egenskaper, undefined-arrayelementer, sparsomme arrays eller objekttypemismatch. For å ta hensyn til disse, bruk .toStrictEqual i stedet.

info

.toEqual utfører ikke en dyp likhets-sjekk for to feil. Kun message-egenskapen til en Error vurderes for likhet. Det anbefales å bruke .toThrow-matcheren for testing mot feil.

Hvis forskjeller mellom egenskaper ikke hjelper deg med å forstå hvorfor en test feiler, spesielt hvis rapporten er stor, kan du flytte sammenligningen inn i expect-funksjonen. For eksempel bruk equals-metoden i Buffer-klassen for å bekrefte om buffere inneholder samme innhold:

  • omskriv expect(received).toEqual(expected) til expect(received.equals(expected)).toBe(true)

  • omskriv expect(received).not.toEqual(expected) til expect(received.equals(expected)).toBe(false)

.toMatch(regexp | string)

Bruk .toMatch for å sjekke at en streng samsvarer med et regulært uttrykk.

For eksempel vet du kanskje ikke nøyaktig hva essayOnTheBestFlavor() returnerer, men du vet at det er en veldig lang streng, og delstrengen grapefruit bør være der et sted. Du kan teste dette med:

describe('an essay on the best flavor', () => {
test('mentions grapefruit', () => {
expect(essayOnTheBestFlavor()).toMatch(/grapefruit/);
expect(essayOnTheBestFlavor()).toMatch(new RegExp('grapefruit'));
});
});

Denne matcheren aksepterer også en streng, som den vil forsøke å matche:

describe('grapefruits are healthy', () => {
test('grapefruits are a fruit', () => {
expect('grapefruits').toMatch('fruit');
});
});

.toMatchObject(object)

Bruk .toMatchObject for å sjekke at et JavaScript-objekt samsvarer med en delmengde av egenskapene til et annet objekt. Den vil matche mottatte objekter med egenskaper som ikke finnes i forventet objekt.

Du kan også sende inn en array av objekter, og i så fall vil metoden kun returnere true hvis hvert objekt i den mottatte arrayen matcher (i toMatchObject-forstand beskrevet ovenfor) det tilsvarende objektet i den forventede arrayen. Dette er nyttig hvis du vil sjekke at to arrays samsvarer i antall elementer, i motsetning til arrayContaining som tillater ekstra elementer i den mottatte arrayen.

Du kan matche egenskaper mot verdier eller mot andre matchere.

const houseForSale = {
bath: true,
bedrooms: 4,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
area: 20,
wallColor: 'white',
},
};
const desiredHouse = {
bath: true,
kitchen: {
amenities: ['oven', 'stove', 'washer'],
wallColor: expect.stringMatching(/white|yellow/),
},
};

test('the house has my desired features', () => {
expect(houseForSale).toMatchObject(desiredHouse);
});
describe('toMatchObject applied to arrays', () => {
test('the number of elements must match exactly', () => {
expect([{foo: 'bar'}, {baz: 1}]).toMatchObject([{foo: 'bar'}, {baz: 1}]);
});

test('.toMatchObject is called for each elements, so extra object properties are okay', () => {
expect([{foo: 'bar'}, {baz: 1, extra: 'quux'}]).toMatchObject([
{foo: 'bar'},
{baz: 1},
]);
});
});

.toMatchSnapshot(propertyMatchers?, hint?)

Dette sikrer at en verdi samsvarer med det siste øyeblikksbildet. Se veiledningen for øyeblikksbildetesting for mer informasjon.

Du kan angi et valgfritt propertyMatchers-objektargument som inneholder asymmetriske matchere som verdier for en delmengde av forventede egenskaper, hvis den mottatte verdien vil være en objekt-instans. Dette fungerer som toMatchObject med fleksible kriterier for en delmengde av egenskaper, etterfulgt av en snapshot-test som eksakte kriterier for de resterende egenskapene.

Du kan angi en valgfri hint-strengargument som legges til testnavnet. Selv om Jest alltid legger til et tall på slutten av et snapshot-navn, kan korte beskrivende hint være mer nyttige enn tall for å skille flere snapshots i et enkelt it- eller test-blokk. Jest sorterer snapshots etter navn i den tilsvarende .snap-filen.

.toMatchInlineSnapshot(propertyMatchers?, inlineSnapshot)

Sikrer at en verdi samsvarer med det siste øyeblikksbildet.

Du kan angi et valgfritt propertyMatchers-objektargument som inneholder asymmetriske matchere som verdier for en delmengde av forventede egenskaper, hvis den mottatte verdien vil være en objekt-instans. Dette fungerer som toMatchObject med fleksible kriterier for en delmengde av egenskaper, etterfulgt av en snapshot-test som eksakte kriterier for de resterende egenskapene.

Jest legger til inlineSnapshot-strengargumentet i matcheren i testfilen (istedenfor en ekstern .snap-fil) første gang testen kjøres.

Se seksjonen om Inline Snapshots for mer informasjon.

.toStrictEqual(value)

Bruk .toStrictEqual for å teste at objekter har samme struktur og type.

Forskjeller fra .toEqual:

  • nøkler med undefined-egenskaper sjekkes, f.eks. vil {a: undefined, b: 2} ikke være lik {b: 2};

  • undefined-elementer tas med i betraktning, f.eks. vil [2] ikke være lik [2, undefined];

  • sparsomhet i arrays sjekkes, f.eks. vil [, 1] ikke være lik [undefined, 1];

  • objekttyper sjekkes, f.eks. vil en klasseinstans med feltene a og b ikke være lik et litterært objekt med feltene a og b.

class LaCroix {
constructor(flavor) {
this.flavor = flavor;
}
}

describe('the La Croix cans on my desk', () => {
test('are not semantically the same', () => {
expect(new LaCroix('lemon')).toEqual({flavor: 'lemon'});
expect(new LaCroix('lemon')).not.toStrictEqual({flavor: 'lemon'});
});
});

.toThrow(error?)

Bruk .toThrow for å teste at en funksjon kaster en feil når den kalles. For eksempel, hvis vi vil teste at drinkFlavor('octopus') kaster en feil fordi blekksmak er for motbydelig å drikke, kan vi skrive:

test('throws on octopus', () => {
expect(() => {
drinkFlavor('octopus');
}).toThrow();
});
tips

Du må pakke koden inn i en funksjon, ellers vil ikke feilen bli fanget og påstanden vil feile.

Du kan angi et valgfritt argument for å teste at en spesifikk feil kastes:

  • regulært uttrykk: feilmeldingen matcher mønsteret

  • streng: feilmeldingen inneholder delstrengen

  • feilobjekt: feilmeldingen er lik meldingsegenskapen til objektet

  • feilklasse: feilobjektet er instans av klassen

For eksempel, la oss si at drinkFlavor er kodet slik:

function drinkFlavor(flavor) {
if (flavor === 'octopus') {
throw new DisgustingFlavorError('yuck, octopus flavor');
}
// Do some other stuff
}

Vi kan teste at denne feilen kastes på flere måter:

test('throws on octopus', () => {
function drinkOctopus() {
drinkFlavor('octopus');
}

// Test that the error message says "yuck" somewhere: these are equivalent
expect(drinkOctopus).toThrow(/yuck/);
expect(drinkOctopus).toThrow('yuck');

// Test the exact error message
expect(drinkOctopus).toThrow(/^yuck, octopus flavor$/);
expect(drinkOctopus).toThrow(new Error('yuck, octopus flavor'));

// Test that we get a DisgustingFlavorError
expect(drinkOctopus).toThrow(DisgustingFlavorError);
});

.toThrowErrorMatchingSnapshot(hint?)

Bruk .toThrowErrorMatchingSnapshot for å teste at en funksjon kaster en feil som matcher det nyeste snapshotet når den kalles.

Du kan angi en valgfri hint-strengargument som legges til testnavnet. Selv om Jest alltid legger til et tall på slutten av et snapshot-navn, kan korte beskrivende hint være mer nyttige enn tall for å skille flere snapshots i et enkelt it- eller test-blokk. Jest sorterer snapshots etter navn i den tilsvarende .snap-filen.

For eksempel, la oss si du har en drinkFlavor-funksjon som alltid kaster en feil når smaken er 'octopus', og er kodet slik:

function drinkFlavor(flavor) {
if (flavor === 'octopus') {
throw new DisgustingFlavorError('yuck, octopus flavor');
}
// Do some other stuff
}

Testen for denne funksjonen vil se slik ut:

test('throws on octopus', () => {
function drinkOctopus() {
drinkFlavor('octopus');
}

expect(drinkOctopus).toThrowErrorMatchingSnapshot();
});

Og den vil generere følgende snapshot:

exports[`drinking flavors throws on octopus 1`] = `"yuck, octopus flavor"`;

Se React Tree Snapshot Testing for mer informasjon om snapshot-testing.

.toThrowErrorMatchingInlineSnapshot(inlineSnapshot)

Bruk .toThrowErrorMatchingInlineSnapshot for å teste at en funksjon kaster en feil som matcher det nyeste inline-snapshotet når den kalles.

Jest legger til inlineSnapshot-strengargumentet i matcheren i testfilen (istedenfor en ekstern .snap-fil) første gang testen kjøres.

Se seksjonen om Inline Snapshots for mer informasjon.

Asymmetriske Matchere

expect.anything()

expect.anything() samsvarer med alt bortsett fra null eller undefined. Du kan bruke den inne i toEqual eller toHaveBeenCalledWith i stedet for en bokstavelig verdi. For eksempel, hvis du vil sjekke at en mock-funksjon kalles med et argument som ikke er null:

test('map calls its argument with a non-null argument', () => {
const mock = jest.fn();
[1].map(x => mock(x));
expect(mock).toHaveBeenCalledWith(expect.anything());
});

expect.any(constructor)

expect.any(constructor) samsvarer med alt som ble opprettet med den gitte konstruktøren eller hvis det er en primitiv type som er av den beståtte typen. Du kan bruke det inne i toEqual eller toHaveBeenCalledWith i stedet for en bokstavelig verdi. For eksempel, hvis du vil sjekke at en mock-funksjon blir kalt med et tall:

class Cat {}
function getCat(fn) {
return fn(new Cat());
}

test('randocall calls its callback with a class instance', () => {
const mock = jest.fn();
getCat(mock);
expect(mock).toHaveBeenCalledWith(expect.any(Cat));
});

function randocall(fn) {
return fn(Math.floor(Math.random() * 6 + 1));
}

test('randocall calls its callback with a number', () => {
const mock = jest.fn();
randocall(mock);
expect(mock).toHaveBeenCalledWith(expect.any(Number));
});

expect.arrayContaining(array)

expect.arrayContaining(array) matcher en mottatt array som inneholder alle elementene i den forventede arrayen. Det vil si at den forventede arrayen er en delmengde av den mottatte arrayen. Derfor matcher den en mottatt array som inneholder elementer som ikke er i den forventede arrayen.

Du kan bruke dette i stedet for en bokstavelig verdi:

  • i toEqual eller toHaveBeenCalledWith

  • for å matche en egenskap i objectContaining eller toMatchObject

describe('arrayContaining', () => {
const expected = ['Alice', 'Bob'];
it('matches even if received contains additional elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected));
});
it('does not match if received does not contain expected elements', () => {
expect(['Bob', 'Eve']).not.toEqual(expect.arrayContaining(expected));
});
});
describe('Beware of a misunderstanding! A sequence of dice rolls', () => {
const expected = [1, 2, 3, 4, 5, 6];
it('matches even with an unexpected number 7', () => {
expect([4, 1, 6, 7, 3, 5, 2, 5, 4, 6]).toEqual(
expect.arrayContaining(expected),
);
});
it('does not match without an expected number 2', () => {
expect([4, 1, 6, 7, 3, 5, 7, 5, 4, 6]).not.toEqual(
expect.arrayContaining(expected),
);
});
});

expect.not.arrayContaining(array)

expect.not.arrayContaining(array) samsvarer med en mottatt matrise som ikke inneholder alle elementene i den forventede matrisen. Det vil si at den forventede matrisen ikke er en delmengde av den mottatte matrisen.

Dette er det motsatte av expect.arrayContaining.

describe('not.arrayContaining', () => {
const expected = ['Samantha'];

it('matches if the actual array does not contain the expected elements', () => {
expect(['Alice', 'Bob', 'Eve']).toEqual(
expect.not.arrayContaining(expected),
);
});
});

expect.arrayOf(value)

expect.arrayOf(value) samsvarer med en mottatt matrise der elementene samsvarer med den angitte verdien. Dette er nyttig for å bekrefte at hvert element i en matrise tilfredsstiller en bestemt betingelse eller type.

Eksempel:

test('all elements in array are strings', () => {
expect(['apple', 'banana', 'cherry']).toEqual(
expect.arrayOf(expect.any(String)),
);
});

Denne matcheren er spesielt nyttig for å validere matriser som inneholder komplekse strukturer:

test('array of objects with specific properties', () => {
expect([
{id: 1, name: 'Alice'},
{id: 2, name: 'Bob'},
]).toEqual(
expect.arrayOf(
expect.objectContaining({
id: expect.any(Number),
name: expect.any(String),
}),
),
);
});

expect.not.arrayOf(value)

expect.not.arrayOf(value)

Eksempel:

test('not all elements in array are strings', () => {
expect(['apple', 123, 'cherry']).toEqual(
expect.not.arrayOf(expect.any(String)),
);
});

expect.closeTo(number, numDigits?)

expect.closeTo(number, numDigits?) er nyttig når du sammenligner flyttall i egenskaper eller matriseelementer. Hvis du trenger å sammenligne et enkelt tall, bruk .toBeCloseTo i stedet.

Den valgfrie numDigits-argumentet begrenser antall sifre som sjekkes etter desimaltegnet. For standardverdien 2 er testkriteriet Math.abs(expected - received) < 0.005 (that is, 10 ** -2 / 2).

For eksempel består denne testen med en presisjon på 5 sifre:

test('compare float in object properties', () => {
expect({
title: '0.1 + 0.2',
sum: 0.1 + 0.2,
}).toEqual({
title: '0.1 + 0.2',
sum: expect.closeTo(0.3, 5),
});
});

expect.objectContaining(object)

expect.objectContaining(object)

I stedet for bokstavelige egenskapsverdier i det forventede objektet, kan du bruke matchere, expect.anything(), og så videre.

For eksempel, la oss si at vi forventer at en onPress-funksjon blir kalt med et Event-objekt, og alt vi trenger å verifisere er at eventen har event.x og event.y-egenskapene. Vi kan gjøre det med:

test('onPress gets called with the right thing', () => {
const onPress = jest.fn();
simulatePresses(onPress);
expect(onPress).toHaveBeenCalledWith(
expect.objectContaining({
x: expect.any(Number),
y: expect.any(Number),
}),
);
});

expect.not.objectContaining(object)

expect.not.objectContaining(object) samsvarer med ethvert mottatt objekt som ikke rekursivt samsvarer med de forventede egenskapene. Det vil si at det forventede objektet ikke er en delmengde av det mottatte objektet. Derfor samsvarer det med et mottatt objekt som inneholder egenskaper som ikke finnes i det forventede objektet.

Det er det motsatte av expect.objectContaining.

describe('not.objectContaining', () => {
const expected = {foo: 'bar'};

it('matches if the actual object does not contain expected key: value pairs', () => {
expect({bar: 'baz'}).toEqual(expect.not.objectContaining(expected));
});
});

expect.stringContaining(string)

expect.stringContaining(string) samsvarer med mottatt verdi hvis den er en streng som inneholder den eksakte forventede strengen.

expect.not.stringContaining(string)

expect.not.stringContaining(string) samsvarer med mottatt verdi hvis den ikke er en streng eller hvis den er en streng som ikke inneholder den eksakte forventede strengen.

Det er det motsatte av expect.stringContaining.

describe('not.stringContaining', () => {
const expected = 'Hello world!';

it('matches if the received value does not contain the expected substring', () => {
expect('How are you?').toEqual(expect.not.stringContaining(expected));
});
});

expect.stringMatching(string | regexp)

expect.stringMatching(string | regexp) samsvarer med mottatt verdi hvis den er en streng som matcher forventet streng eller regulært uttrykk.

Du kan bruke dette i stedet for en bokstavelig verdi:

  • i toEqual eller toHaveBeenCalledWith

  • for å matche et element i arrayContaining

  • for å matche en egenskap i objectContaining eller toMatchObject

Dette eksemplet viser også hvordan du kan sette sammen flere asymmetriske matchere, med expect.stringMatching inni expect.arrayContaining.

describe('stringMatching in arrayContaining', () => {
const expected = [
expect.stringMatching(/^Alic/),
expect.stringMatching(/^[BR]ob/),
];
it('matches even if received contains additional elements', () => {
expect(['Alicia', 'Roberto', 'Evelina']).toEqual(
expect.arrayContaining(expected),
);
});
it('does not match if received does not contain expected elements', () => {
expect(['Roberto', 'Evelina']).not.toEqual(
expect.arrayContaining(expected),
);
});
});

expect.not.stringMatching(string | regexp)

expect.not.stringMatching(string | regexp) samsvarer med mottatt verdi hvis den ikke er en streng eller hvis den er en streng som ikke matcher forventet streng eller regulært uttrykk.

Det er det motsatte av expect.stringMatching.

describe('not.stringMatching', () => {
const expected = /Hello world!/;

it('matches if the received value does not match the expected regex', () => {
expect('How are you?').toEqual(expect.not.stringMatching(expected));
});
});

Assertion-telling

expect.assertions(number)

expect.assertions(number) verifiserer at et bestemt antall assertions blir kalt under en test. Dette er ofte nyttig ved testing av asynkron kode for å sikre at assertions i en callback faktisk blir kalt.

La oss si at vi har en funksjon doAsync som mottar to callbacks callback1 og callback2, og asynkront kaller begge i ukjent rekkefølge. Vi kan teste dette med:

test('doAsync calls both callbacks', () => {
expect.assertions(2);
function callback1(data) {
expect(data).toBeTruthy();
}
function callback2(data) {
expect(data).toBeTruthy();
}

doAsync(callback1, callback2);
});

Kallet expect.assertions(2) sikrer at begge callbacks faktisk blir kalt.

expect.hasAssertions()

expect.hasAssertions() verifiserer at minst én assertion blir kalt under en test. Dette er ofte nyttig ved testing av asynkron kode for å sikre at assertions i en callback faktisk blir kalt.

La oss si at vi har noen funksjoner som håndterer tilstand. prepareState kaller en callback med et tilstandsobjekt, validateState kjører på det tilstandsobjektet, og waitOnState returner et løfte som venter til alle prepareState-callbacks er ferdige. Vi kan teste dette med:

test('prepareState prepares a valid state', () => {
expect.hasAssertions();
prepareState(state => {
expect(validateState(state)).toBeTruthy();
});
return waitOnState();
});

Kallet expect.hasAssertions() sikrer at prepareState-callbacken faktisk blir kalt.

Utvidelsesverktøy

expect.addEqualityTesters(testers)

Du kan bruke expect.addEqualityTesters for å legge til egne metoder for å teste om to objekter er like. For eksempel, la oss si at du har en klasse i koden din som representerer volum og kan avgjøre om to volumer med ulike enheter er like. Du vil kanskje at toEqual (og andre likhetsmatchere) skal bruke denne egendefinerte likhetsmetoden når de sammenligner Volum-klasser. Du kan legge til en egendefinert likhetstester for at toEqual skal oppdage og bruke egendefinert logikk ved sammenligning av Volum-klasser:

Volume.js
// For simplicity in this example, we'll just support the units 'L' and 'mL'
export class Volume {
constructor(amount, unit) {
this.amount = amount;
this.unit = unit;
}

toString() {
return `[Volume ${this.amount}${this.unit}]`;
}

equals(other) {
if (this.unit === other.unit) {
return this.amount === other.amount;
} else if (this.unit === 'L' && other.unit === 'mL') {
return this.amount * 1000 === other.unit;
} else {
return this.amount === other.unit * 1000;
}
}
}
areVolumesEqual.js
import {expect} from '@jest/globals';
import {Volume} from './Volume.js';

function areVolumesEqual(a, b) {
const isAVolume = a instanceof Volume;
const isBVolume = b instanceof Volume;

if (isAVolume && isBVolume) {
return a.equals(b);
} else if (isAVolume === isBVolume) {
return undefined;
} else {
return false;
}
}

expect.addEqualityTesters([areVolumesEqual]);
__tests__/Volume.test.js
import {expect, test} from '@jest/globals';
import {Volume} from '../Volume.js';
import '../areVolumesEqual.js';

test('are equal with different units', () => {
expect(new Volume(1, 'L')).toEqual(new Volume(1000, 'mL'));
});

API for egendefinerte likhetstestere

Egendefinerte testere er funksjoner som returnerer enten resultatet (true eller false) av sammenligningen av de to gitte argumentene, eller undefined hvis testverktøyet ikke håndterer de gitte objektene og vil delegere likhet til andre testverktøy (for eksempel de innebygde likhetstesterne).

Egendefinerte testverktøy kalles med 3 argumenter: de to objektene som skal sammenlignes og en array med egendefinerte testverktøy (brukes til rekursive testverktøy, se avsnittet nedenfor).

Disse hjelpefunksjonene og egenskapene finnes på this inne i et egendefinert testverktøy:

this.equals(a, b, customTesters?)

Dette er en funksjon for dyp likhet som returnerer true hvis to objekter har identiske verdier (rekursivt). Den kan valgfritt ta en liste med tilpassede likhetstestere for dype likhetsjekker. Hvis du bruker denne funksjonen, må du videresende de tilpassede testerne som er gitt til din tester, slik at videre likhetsjekker som equals utfører også kan bruke tilpassede testere som testforfatteren kan ha konfigurert. Se eksempelet i avsnittet Rekursive tilpassede likhetstestere for detaljer.

Matchers vs Testers

Matchers er metoder tilgjengelige på expect, for eksempel expect().toEqual(). toEqual er en matcher. En tester er en metode som brukes av matchers for likhetsjekker for å avgjøre om objekter er identiske.

Tilpassede matchers er nyttige når du vil tilby egendefinerte påstander testforfattere kan bruke. For eksempel er toBeWithinRange-eksempelet i avsnittet expect.extend et godt eksempel på en tilpasset matcher. Noen ganger vil en testforfatter bekrefte at tall er nøyaktig like med toBe, mens andre ganger trengs fleksibilitet hvor toBeWithinRange passer bedre.

Tilpassede likhetstestere er ideelle for global utvidelse av Jest-matchers med egendefinert likhetslogikk. Testforfattere kan ikke aktivere tilpassede testere for enkelte påstander og deaktivere for andre (da bør en tilpasset matcher brukes). For eksempel vil definering av likhetsjekk for Volume-objekter være passende som tilpasset likhetstester.

Rekursive tilpassede likhetstestere

Hvis dine tilpassede likhetstestere sjekker objekter med egenskaper som krever dyp likhet, bruk this.equals-hjelperen. Denne equals-metoden er den samme dypelikhetsmetoden Jest bruker internt, og den aktiverer din tilpassede tester. Den tar en matrise med tilpassede testere som tredje argument. Videresend dette argumentet til equals for at dype objektsjekker også kan benytte tilpassede testere.

For eksempel: Anta en Book-klasse som inneholder Author-objekter med egne testere. Book-testeren må utføre dyp likhetsjekk på Author-matrisen og videresende mottatte testere, slik at Author sin egen likhetstester blir brukt:

customEqualityTesters.js
function areAuthorEqual(a, b) {
const isAAuthor = a instanceof Author;
const isBAuthor = b instanceof Author;

if (isAAuthor && isBAuthor) {
// Authors are equal if they have the same name
return a.name === b.name;
} else if (isAAuthor === isBAuthor) {
return undefined;
} else {
return false;
}
}

function areBooksEqual(a, b, customTesters) {
const isABook = a instanceof Book;
const isBBook = b instanceof Book;

if (isABook && isBBook) {
// Books are the same if they have the same name and author array. We need
// to pass customTesters to equals here so the Author custom tester will be
// used when comparing Authors
return (
a.name === b.name && this.equals(a.authors, b.authors, customTesters)
);
} else if (isABook === isBBook) {
return undefined;
} else {
return false;
}
}

expect.addEqualityTesters([areAuthorsEqual, areBooksEqual]);
notat

Definer likhetstestere som vanlige funksjoner, ikke pilfunksjoner, for å få tilgang til konteksthjelpere som this.equals.

expect.addSnapshotSerializer(serializer)

Bruk expect.addSnapshotSerializer for å legge til en modul som formaterer applikasjonsspesifikke datastrukturer.

For individuelle testfiler prioriteres tilføyde moduler over snapshotSerializers-konfigurasjon, som igjen går foran standardserialiserere for JavaScript-typer og React-elementer. Siste tilføyde modul testes først.

import serializer from 'my-serializer-module';
expect.addSnapshotSerializer(serializer);

// affects expect(value).toMatchSnapshot() assertions in the test file

Hvis du legger til en snapshot-serializer i individuelle testfiler i stedet for å legge den til snapshotSerializers-konfigurasjonen:

  • Gjøres avhengigheter eksplisitte istedenfor implisitte

  • Unngås konfigurasjonsbegrensninger som kan tvinge deg ut av create-react-app

Se Jest-konfigurasjon for detaljer.

expect.extend(matchers)

Bruk expect.extend for å legge til egne matchers i Jest. For eksempel: Dersom du tester et tallverktøysbibliotek og ofte verifiserer at tall ligger innenfor spesifikke intervaller, kan du abstrahere dette til en toBeWithinRange-matcher:

toBeWithinRange.js
import {expect} from '@jest/globals';

function toBeWithinRange(actual, floor, ceiling) {
if (
typeof actual !== 'number' ||
typeof floor !== 'number' ||
typeof ceiling !== 'number'
) {
throw new TypeError('These must be of type number!');
}

const pass = actual >= floor && actual <= ceiling;
if (pass) {
return {
message: () =>
`expected ${this.utils.printReceived(
actual,
)} not to be within range ${this.utils.printExpected(
`${floor} - ${ceiling}`,
)}`,
pass: true,
};
} else {
return {
message: () =>
`expected ${this.utils.printReceived(
actual,
)} to be within range ${this.utils.printExpected(
`${floor} - ${ceiling}`,
)}`,
pass: false,
};
}
}

expect.extend({
toBeWithinRange,
});
__tests__/ranges.test.js
import {expect, test} from '@jest/globals';
import '../toBeWithinRange';

test('is within range', () => expect(100).toBeWithinRange(90, 110));

test('is NOT within range', () => expect(101).not.toBeWithinRange(0, 100));

test('asymmetric ranges', () => {
expect({apples: 6, bananas: 3}).toEqual({
apples: expect.toBeWithinRange(1, 10),
bananas: expect.not.toBeWithinRange(11, 20),
});
});
toBeWithinRange.d.ts
// optionally add a type declaration, e.g. it enables autocompletion in IDEs
declare module 'expect' {
interface AsymmetricMatchers {
toBeWithinRange(floor: number, ceiling: number): void;
}
interface Matchers<R> {
toBeWithinRange(floor: number, ceiling: number): R;
}
}

export {};
tips

Typedeclarasjonen for matcheren kan ligge i en .d.ts-fil eller i en importert .ts-modul (se henholdsvis JS- og TS-eksemplene ovenfor). Hvis du oppbevarer deklarasjonen i en .d.ts-fil, sørg for at den er inkludert i programmet og at den er en gyldig modul, dvs. at den har minst en tom export {}.

tips

I stedet for å importere toBeWithinRange-modulen til testfilen, kan du aktivere matcheren for alle tester ved å flytte expect.extend-kallet til et setupFilesAfterEnv-skript:

import {expect} from '@jest/globals';
// remember to export `toBeWithinRange` as well
import {toBeWithinRange} from './toBeWithinRange';

expect.extend({
toBeWithinRange,
});

Asynkrone matchere

expect.extend støtter også asynkrone matchere. Asynkrone matchere returnerer et Promise, så du må vente på den returnerte verdien. La oss bruke en eksempelmatcher for å illustrere bruken. Vi skal implementere en matcher kalt toBeDivisibleByExternalValue, hvor det delbare tallet hentes fra en ekstern kilde.

expect.extend({
async toBeDivisibleByExternalValue(received) {
const externalValue = await getExternalValueFromRemoteSource();
const pass = received % externalValue === 0;
if (pass) {
return {
message: () =>
`expected ${received} not to be divisible by ${externalValue}`,
pass: true,
};
} else {
return {
message: () =>
`expected ${received} to be divisible by ${externalValue}`,
pass: false,
};
}
},
});

test('is divisible by external value', async () => {
await expect(100).toBeDivisibleByExternalValue();
await expect(101).not.toBeDivisibleByExternalValue();
});

API for egendefinerte matchere

Matchere bør returnere et objekt (eller et Promise av et objekt) med to nøkler. pass indikerer om det var en match eller ikke, og message gir en funksjon uten argumenter som returnerer en feilmelding ved feil. Når pass er false, bør message returnere feilmeldingen for når expect(x).yourMatcher() feiler. Når pass er true, bør message returnere feilmeldingen for når expect(x).not.yourMatcher() feiler.

Matchere kalles med argumentet gitt til expect(x) fulgt av argumentene gitt til .yourMatcher(y, z):

expect.extend({
yourMatcher(x, y, z) {
return {
pass: true,
message: () => '',
};
},
});

Disse hjelpefunksjonene og egenskapene finnes på this inne i en egendefinert matcher:

this.isNot

En boolsk verdi som forteller deg om denne matcheren ble kalt med den negerte .not-modifikatoren, slik at du kan vise en tydelig og korrekt matcher-hint (se eksempelkode).

this.promise

En streng som lar deg vise en tydelig og korrekt matcher-hint:

  • 'rejects' hvis matcheren ble kalt med promise-modifikatoren .rejects

  • 'resolves' hvis matcheren ble kalt med promise-modifikatoren .resolves

  • '' hvis matcheren ikke ble kalt med en promise-modifikator

this.equals(a, b, customTesters?)

Dette er en dyp-likhetsfunksjon som returnerer true hvis to objekter har samme verdier (rekursivt). Den kan ta en liste med egendefinerte likhetstester som valgfritt argument for å brukes i de dype likhetssjekkene (se this.customTesters nedenfor).

this.expand

En boolsk verdi som forteller deg om denne matcheren ble kalt med et expand-alternativ. Når Jest kjøres med --expand-flagget, kan this.expand brukes for å avgjøre om Jest skal vise fulle diff-er og feil.

this.utils

Det finnes en rekke nyttige verktøy tilgjengelig på this.utils, hovedsakelig eksportert fra jest-matcher-utils.

De mest nyttige er matcherHint, printExpected og printReceived for å formatere feilmeldingene pent. Ta for eksempel en titt på implementeringen av toBe-matcheren:

const {diff} = require('jest-diff');
expect.extend({
toBe(received, expected) {
const options = {
comment: 'Object.is equality',
isNot: this.isNot,
promise: this.promise,
};

const pass = Object.is(received, expected);

const message = pass
? () =>
// eslint-disable-next-line prefer-template
this.utils.matcherHint('toBe', undefined, undefined, options) +
'\n\n' +
`Expected: not ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(received)}`
: () => {
const diffString = diff(expected, received, {
expand: this.expand,
});
return (
// eslint-disable-next-line prefer-template
this.utils.matcherHint('toBe', undefined, undefined, options) +
'\n\n' +
(diffString && diffString.includes('- Expect')
? `Difference:\n\n${diffString}`
: `Expected: ${this.utils.printExpected(expected)}\n` +
`Received: ${this.utils.printReceived(received)}`)
);
};

return {actual: received, message, pass};
},
});

Dette vil skrive ut noe som dette:

  expect(received).toBe(expected)

Expected value to be (using Object.is):
"banana"
Received:
"apple"

Når en påstand feiler, bør feilmeldingen gi så mye informasjon som nødvendig til brukeren slik at de raskt kan løse problemet. Du bør lage en presis feilmelding for å sikre at brukerne av dine egendefinerte påstander får en god utvikleropplevelse.

this.customTesters

Hvis din matcher utfører en dyp likhetssjekk ved hjelp av this.equals, kan det være lurt å sende brukerdefinerte testfunksjoner til this.equals. De tilpassede likhetstestene brukeren har lagt til via addEqualityTesters-APIet er tilgjengelige i denne egenskapen. De innebygde Jest-matcherne sender this.customTesters (sammen med andre innebygde testere) til this.equals for dype likhetssjekker, og dine egendefinerte matchers kan gjøre det samme.

Egendefinerte snapshot-matchers

For å bruke snapshot-testing i dine egendefinerte matchers kan du importere jest-snapshot og bruke den i matcheren din.

Her er en snapshot-matcher som trimmer en streng til en gitt lengde, .toMatchTrimmedSnapshot(length):

const {toMatchSnapshot} = require('jest-snapshot');

expect.extend({
toMatchTrimmedSnapshot(received, length) {
return toMatchSnapshot.call(
this,
received.slice(0, length),
'toMatchTrimmedSnapshot',
);
},
});

it('stores only 10 characters', () => {
expect('extra long string oh my gerd').toMatchTrimmedSnapshot(10);
});

/*
Stored snapshot will look like:

exports[`stores only 10 characters: toMatchTrimmedSnapshot 1`] = `"extra long"`;
*/

Det er også mulig å lage egendefinerte matchers for inline-snapshots. Snapshots vil bli lagt til riktig i de egendefinerte matcherene. Men inline-snapshots vil alltid prøve å legge til det første argumentet eller det andre når første argument er en egenskapsmatcher, så det er ikke mulig å akseptere egendefinerte argumenter i egendefinerte matchers.

const {toMatchInlineSnapshot} = require('jest-snapshot');

expect.extend({
toMatchTrimmedInlineSnapshot(received, ...rest) {
return toMatchInlineSnapshot.call(this, received.slice(0, 10), ...rest);
},
});

it('stores only 10 characters', () => {
expect('extra long string oh my gerd').toMatchTrimmedInlineSnapshot();
/*
The snapshot will be added inline like
expect('extra long string oh my gerd').toMatchTrimmedInlineSnapshot(
`"extra long"`
);
*/
});

async

Hvis din egendefinerte inline-snapshot-matcher er asynkron (dvs. bruker async-await), kan du støte på en feil som "Flere inline-snapshots for samme kall støttes ikke". Jest trenger ekstra kontekstinformasjon for å finne hvor den egendefinerte inline-snapshot-matcheren ble brukt for å oppdatere snapshots riktig.

const {toMatchInlineSnapshot} = require('jest-snapshot');

expect.extend({
async toMatchObservationInlineSnapshot(fn, ...rest) {
// The error (and its stacktrace) must be created before any `await`
this.error = new Error();

// The implementation of `observe` doesn't matter.
// It only matters that the custom snapshot matcher is async.
const observation = await observe(async () => {
await fn();
});

return toMatchInlineSnapshot.call(this, recording, ...rest);
},
});

it('observes something', async () => {
await expect(async () => {
return 'async action';
}).toMatchTrimmedInlineSnapshot();
/*
The snapshot will be added inline like
await expect(async () => {
return 'async action';
}).toMatchTrimmedInlineSnapshot(`"async action"`);
*/
});

Avbryt test

Vanligvis prøver jest å matche alle snapshots som forventes i en test.

Noen ganger gir det kanskje ikke mening å fortsette testen hvis et tidligere snapshot feilet. For eksempel, når du tar snapshots av en tilstandsmaskin etter ulike overganger, kan du avbryte testen hvis én overgang produserte feil tilstand.

I slike tilfeller kan du implementere en egendefinert snapshot-matcher som kaster en feil ved første avvik i stedet for å samle alle avvik.

const {toMatchInlineSnapshot} = require('jest-snapshot');

expect.extend({
toMatchStateInlineSnapshot(...args) {
this.dontThrow = () => {};

return toMatchInlineSnapshot.call(this, ...args);
},
});

let state = 'initial';

function transition() {
// Typo in the implementation should cause the test to fail
if (state === 'INITIAL') {
state = 'pending';
} else if (state === 'pending') {
state = 'done';
}
}

it('transitions as expected', () => {
expect(state).toMatchStateInlineSnapshot(`"initial"`);

transition();
// Already produces a mismatch. No point in continuing the test.
expect(state).toMatchStateInlineSnapshot(`"loading"`);

transition();
expect(state).toMatchStateInlineSnapshot(`"done"`);
});

Serialiserbare egenskaper

SERIALIZABLE_PROPERTIES

Serialiserbare egenskaper er et sett med egenskaper som Jest anser som serialiserbare. Dette settet brukes for å avgjøre om en egenskap bør være serialiserbar eller ikke. Hvis et objekt har en egenskap som ikke er i dette settet, anses den som ikke-serialiserbar og vil ikke vises i feilmeldinger.

Du kan legge til dine egne egenskaper i dette settet for å sikre at objektene dine vises riktig. For eksempel, hvis du har en Volume-klasse og kun ønsker at amount og unit-egenskapene skal vises, kan du legge den til i SERIALIZABLE_PROPERTIES:

import {SERIALIZABLE_PROPERTIES} from 'jest-matcher-utils';

class Volume {
constructor(amount, unit) {
this.amount = amount;
this.unit = unit;
}

get label() {
throw new Error('Not implemented');
}
}

Volume.prototype[SERIALIZABLE_PROPERTIES] = ['amount', 'unit'];

expect(new Volume(1, 'L')).toEqual(new Volume(10, 'L'));

Dette vil kun vise amount og unit-egenskapene i feilmeldingen, og ignorere label-egenskapen.

expect(received).toEqual(expected) // deep equality

Expected: {"amount": 10, "unit": "L"}
Received: {"amount": 1, "unit": "L"}