expect
Gerne, hier ist die optimierte deutsche Version Ihres Vitest 3-Dokuments:
type Awaitable<T> = T | PromiseLike<T>;
expect
wird verwendet, um Zusicherungen (Assertions) zu erstellen. In diesem Kontext sind Assertions
Funktionen, die aufgerufen werden, um eine Aussage zu überprüfen. Vitest bietet standardmäßig chai
-Assertions sowie Jest
-kompatible Assertions, die auf chai
basieren. Im Gegensatz zu Jest
unterstützt Vitest eine Nachricht als zweites Argument: Schlägt die Assertion fehl, wird diese Nachricht als Fehlermeldung ausgegeben.
export interface ExpectStatic
extends Chai.ExpectStatic,
AsymmetricMatchersContaining {
<T>(actual: T, message?: string): Assertion<T>;
extend: (expects: MatchersObject) => void;
anything: () => any;
any: (constructor: unknown) => any;
getState: () => MatcherState;
setState: (state: Partial<MatcherState>) => void;
not: AsymmetricMatchersContaining;
}
Zum Beispiel bestätigt dieser Code, dass ein input
-Wert gleich 2
ist. Andernfalls löst die Assertion einen Fehler aus, und der Test schlägt fehl.
import { expect } from 'vitest';
const input = Math.sqrt(4);
expect(input).to.equal(2); // chai API
expect(input).toBe(2); // jest API
Technisch gesehen verwendet dieses Beispiel keine test
-Funktion, sodass in der Konsole ein Node.js-Fehler anstelle der Vitest-Ausgabe angezeigt wird. Um mehr über test
zu erfahren, lesen Sie bitte die Test API Referenz.
Darüber hinaus kann expect
statisch verwendet werden, um auf später beschriebene Matcher-Funktionen und weitere Funktionalitäten zuzugreifen.
WARNING
expect
beeinflusst die Typüberprüfung nicht, wenn der Ausdruck keinen Typfehler aufweist. Wenn Sie Vitest als Typ-Checker nutzen möchten, verwenden Sie expectTypeOf
oder assertType
.
soft
- Typ:
ExpectStatic & (actual: any) => Assertions
expect.soft
funktioniert ähnlich wie expect
, aber anstatt die Testausführung bei einer fehlgeschlagenen Assertion zu beenden, setzt es die Ausführung fort und markiert den Fehler als Testfehler. Alle während des Tests aufgetretenen Fehler werden angezeigt, bis der Test vollständig durchgelaufen ist.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // markiert den Test als fehlgeschlagen und fährt fort
expect.soft(1 + 2).toBe(4); // markiert den Test als fehlgeschlagen und fährt fort
});
// Der Reporter meldet beide Fehler am Ende der Ausführung
Es kann auch in Kombination mit expect
verwendet werden. Wenn eine expect
-Assertion fehlschlägt, wird der Test beendet und alle vorherigen Fehler werden angezeigt.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // markiert den Test als fehlgeschlagen und fährt fort
expect(1 + 2).toBe(4); // schlägt fehl und beendet den Test; alle vorherigen Fehler werden ausgegeben
expect.soft(1 + 3).toBe(5); // wird nicht ausgeführt
});
WARNING
expect.soft
kann nur innerhalb der test
-Funktion verwendet werden.
poll
interface ExpectPoll extends ExpectStatic {
(actual: () => T, options: { interval; timeout; message }): Promise<
Assertions<T>
>;
}
expect.poll
führt die Assertion wiederholt aus, bis sie erfolgreich ist. Sie können konfigurieren, wie oft Vitest den expect.poll
-Callback erneut ausführen soll, indem Sie die Optionen interval
und timeout
festlegen.
Tritt im expect.poll
-Callback ein Fehler auf, wiederholt Vitest den Versuch, bis das Timeout abläuft.
import { expect, test } from 'vitest';
test('element exists', async () => {
asyncInjectElement();
await expect.poll(() => document.querySelector('.element')).toBeTruthy();
});
WARNING
expect.poll
macht jede Assertion asynchron, daher müssen Sie asynchron darauf warten. Seit Vitest 3 schlägt der Test fehl, wenn Sie vergessen, asynchron darauf zu warten, und gibt eine entsprechende Warnung aus.
expect.poll
funktioniert nicht mit mehreren Matchern:
- Snapshot-Matcher werden nicht unterstützt, da sie immer erfolgreich sind. Wenn Ihre Bedingung unzuverlässig ist, verwenden Sie stattdessen
vi.waitFor
, um sie zuerst aufzulösen:
import { expect, vi } from 'vitest';
const flakyValue = await vi.waitFor(() => getFlakyValue());
expect(flakyValue).toMatchSnapshot();
.resolves
und.rejects
werden nicht unterstützt.expect.poll
wartet bereits asynchron auf die Bedingung, wenn diese asynchron ist.toThrow
und seine Aliase werden nicht unterstützt, da dieexpect.poll
-Bedingung immer aufgelöst wird, bevor der Matcher den Wert empfängt.
not
Mit not
wird die Assertion negiert. Zum Beispiel bestätigt dieser Code, dass ein input
-Wert nicht gleich 2
ist. Wenn er gleich ist, löst die Assertion einen Fehler aus, und der Test schlägt fehl.
import { expect, test } from 'vitest';
const input = Math.sqrt(16);
expect(input).not.to.equal(2); // chai API
expect(input).not.toBe(2); // jest API
toBe
- Typ:
(value: any) => Awaitable<void>
toBe
kann verwendet werden, um zu bestätigen, ob Primitive gleich sind oder ob Objekte dieselbe Referenz teilen. Es ist äquivalent zum Aufruf von expect(Object.is(3, 3)).toBe(true)
. Wenn die Objekte nicht identisch sind, Sie aber ihre Strukturen prüfen möchten, können Sie toEqual
verwenden.
Zum Beispiel prüft der folgende Code, ob der Händler 13 Äpfel hat.
import { expect, test } from 'vitest';
const stock = {
type: 'apples',
count: 13,
};
test('stock has 13 apples', () => {
expect(stock.type).toBe('apples');
expect(stock.count).toBe(13);
});
test('stocks are the same', () => {
const refStock = stock; // gleiche Referenz
expect(stock).toBe(refStock);
});
Vermeiden Sie es, toBe
mit Gleitkommazahlen zu verwenden. Da JavaScript sie rundet, ist 0.1 + 0.2
nicht exakt 0.3
. Um Gleitkommazahlen zuverlässig zu bestätigen, verwenden Sie die Assertion toBeCloseTo
.
toBeCloseTo
- Typ:
(value: number, numDigits?: number) => Awaitable<void>
Verwenden Sie toBeCloseTo
, um Gleitkommazahlen zu vergleichen. Das optionale Argument numDigits
begrenzt die Anzahl der zu prüfenden Ziffern nach dem Dezimalpunkt. Zum Beispiel:
import { expect, test } from 'vitest';
test.fails('Dezimalzahlen sind in JavaScript nicht gleich', () => {
expect(0.2 + 0.1).toBe(0.3); // 0.2 + 0.1 ist 0.30000000000000004
});
test('Dezimalzahlen werden auf 5 Stellen nach dem Komma gerundet', () => {
// 0.2 + 0.1 ist 0.30000 | "000000000004" entfernt
expect(0.2 + 0.1).toBeCloseTo(0.3, 5);
// nichts von 0.30000000000000004 wird entfernt
expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50);
});
toBeDefined
- Typ:
() => Awaitable<void>
toBeDefined
bestätigt, dass der Wert nicht gleich undefined
ist. Ein nützlicher Anwendungsfall ist es, zu prüfen, ob eine Funktion etwas zurückgegeben hat.
import { expect, test } from 'vitest';
function getApples() {
return 3;
}
test('Funktion hat etwas zurückgegeben', () => {
expect(getApples()).toBeDefined();
});
toBeUndefined
- Typ:
() => Awaitable<void>
Im Gegensatz zu toBeDefined
bestätigt toBeUndefined
, dass der Wert gleich undefined
ist. Ein nützlicher Anwendungsfall ist es, zu prüfen, ob eine Funktion nichts zurückgegeben hat.
import { expect, test } from 'vitest';
function getApplesFromStock(stock: string) {
if (stock === 'Bill') {
return 13;
}
}
test("Mary hat keinen Bestand", () => {
expect(getApplesFromStock('Mary')).toBeUndefined();
});
toBeTruthy
- Typ:
() => Awaitable<void>
toBeTruthy
bestätigt, dass der Wert true
ist, wenn er in einen booleschen Wert umgewandelt wird. Nützlich, wenn Ihnen der genaue Wert unwichtig ist, Sie aber nur wissen möchten, ob er in true
umgewandelt werden kann.
Zum Beispiel spielt bei diesem Code der Rückgabewert von stocks.getInfo
keine Rolle – es kann ein komplexes Objekt, ein String oder etwas anderes sein. Der Code funktioniert trotzdem.
import { Stocks } from './stocks.js';
const stocks = new Stocks();
stocks.sync('Bill');
if (stocks.getInfo('Bill')) {
stocks.sell('apples', 'Bill');
}
Wenn Sie also testen möchten, dass stocks.getInfo
truthy ist, könnten Sie schreiben:
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';
const stocks = new Stocks();
test('wenn wir Bills Bestand kennen, verkaufen wir ihm Äpfel', () => {
stocks.sync('Bill');
expect(stocks.getInfo('Bill')).toBeTruthy();
});
Alles in JavaScript ist truthy, außer false
, null
, undefined
, NaN
, 0
, -0
, 0n
, ""
und document.all
.
toBeFalsy
- Typ:
() => Awaitable<void>
toBeFalsy
bestätigt, dass der Wert false
ist, wenn er in einen booleschen Wert umgewandelt wird. Nützlich, wenn Ihnen der genaue Wert unwichtig ist, Sie aber nur wissen möchten, ob er in false
umgewandelt werden kann.
Zum Beispiel spielt bei diesem Code der Rückgabewert von stocks.stockFailed
keine Rolle – er kann jeden falsy Wert zurückgeben, aber der Code funktioniert trotzdem.
import { Stocks } from './stocks.js';
const stocks = new Stocks();
stocks.sync('Bill');
if (!stocks.stockFailed('Bill')) {
stocks.sell('apples', 'Bill');
}
Wenn Sie also testen möchten, dass stocks.stockFailed
falsy ist, könnten Sie schreiben:
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';
const stocks = new Stocks();
test("wenn Bills Bestand nicht fehlgeschlagen ist, verkaufen wir ihm Äpfel", () => {
stocks.syncStocks('Bill');
expect(stocks.stockFailed('Bill')).toBeFalsy();
});
Alles in JavaScript ist truthy, außer false
, null
, undefined
, NaN
, 0
, -0
, 0n
, ""
und document.all
.
toBeNull
- Typ:
() => Awaitable<void>
toBeNull
bestätigt einfach, ob etwas null
ist. Alias für .toBe(null)
.
import { expect, test } from 'vitest';
function apples() {
return null;
}
test("wir haben keine Äpfel", () => {
expect(apples()).toBeNull();
});
toBeNaN
- Typ:
() => Awaitable<void>
toBeNaN
prüft einfach, ob etwas NaN
ist. Alias für .toBe(NaN)
.
import { expect, test } from 'vitest';
let i = 0;
function getApplesCount() {
i++;
return i > 1 ? Number.NaN : i;
}
test('getApplesCount hat einige ungewöhnliche Nebeneffekte...', () => {
expect(getApplesCount()).not.toBeNaN();
expect(getApplesCount()).toBeNaN();
});
toBeOneOf
- Typ:
(sample: Array<any>) => any
toBeOneOf
bestätigt, ob ein Wert mit einem der Werte im bereitgestellten Array übereinstimmt.
import { expect, test } from 'vitest';
test('Frucht ist einer der erlaubten Werte', () => {
expect(fruit).toBeOneOf(['Apfel', 'Banane', 'Orange']);
});
Der asymmetrische Matcher ist besonders nützlich beim Testen optionaler Eigenschaften, die entweder null
oder undefined
sein können:
test('optionale Eigenschaften können null oder undefined sein', () => {
const user = {
firstName: 'John',
middleName: undefined,
lastName: 'Doe',
};
expect(user).toEqual({
firstName: expect.any(String),
middleName: expect.toBeOneOf([expect.any(String), undefined]),
lastName: expect.any(String),
});
});
TIP
Sie können expect.not
mit diesem Matcher verwenden, um sicherzustellen, dass ein Wert NICHT mit einer der bereitgestellten Optionen übereinstimmt.
toBeTypeOf
- Typ:
(c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>
toBeTypeOf
bestätigt, ob ein tatsächlicher Wert vom Typ des erwarteten Typs ist.
import { expect, test } from 'vitest';
const actual = 'stock';
test('stock ist vom Typ string', () => {
expect(actual).toBeTypeOf('string');
});
toBeInstanceOf
- Typ:
(c: any) => Awaitable<void>
toBeInstanceOf
bestätigt, ob ein tatsächlicher Wert eine Instanz der empfangenen Klasse ist.
import { expect, test } from 'vitest';
import { Stocks } from './stocks.js';
const stocks = new Stocks();
test('stocks sind Instanz von Stocks', () => {
expect(stocks).toBeInstanceOf(Stocks);
});
toBeGreaterThan
- Typ:
(n: number | bigint) => Awaitable<void>
toBeGreaterThan
bestätigt, ob der tatsächliche Wert größer ist als der empfangene. Gleiche Werte führen zum Fehlschlagen des Tests.
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';
test('habe mehr als 10 Äpfel', () => {
expect(getApples()).toBeGreaterThan(10);
});
toBeGreaterThanOrEqual
- Typ:
(n: number | bigint) => Awaitable<void>
toBeGreaterThanOrEqual
bestätigt, ob der tatsächliche Wert größer oder gleich dem empfangenen ist.
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';
test('habe 11 Äpfel oder mehr', () => {
expect(getApples()).toBeGreaterThanOrEqual(11);
});
toBeLessThan
- Typ:
(n: number | bigint) => Awaitable<void>
toBeLessThan
bestätigt, ob der tatsächliche Wert kleiner ist als der empfangene. Gleiche Werte führen zum Fehlschlagen des Tests.
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';
test('habe weniger als 20 Äpfel', () => {
expect(getApples()).toBeLessThan(20);
});
toBeLessThanOrEqual
- Typ:
(n: number | bigint) => Awaitable<void>
toBeLessThanOrEqual
bestätigt, ob der tatsächliche Wert kleiner oder gleich dem empfangenen ist.
import { expect, test } from 'vitest';
import { getApples } from './stocks.js';
test('habe 11 Äpfel oder weniger', () => {
expect(getApples()).toBeLessThanOrEqual(11);
});
toEqual
- Typ:
(received: any) => Awaitable<void>
toEqual
bestätigt, ob der tatsächliche Wert dem empfangenen entspricht oder dieselbe Struktur hat, wenn es sich um ein Objekt handelt (vergleicht sie rekursiv). Den Unterschied zwischen toEqual
und toBe
können Sie in diesem Beispiel sehen:
import { expect, test } from 'vitest';
const stockBill = {
type: 'apples',
count: 13,
};
const stockMary = {
type: 'apples',
count: 13,
};
test('Bestände haben die gleichen Eigenschaften', () => {
expect(stockBill).toEqual(stockMary);
});
test('Bestände sind nicht gleich', () => {
expect(stockBill).not.toBe(stockMary);
});
WARNING
Bei Error
-Objekten werden auch nicht-enumerierbare Eigenschaften wie name
, message
, cause
und AggregateError.errors
verglichen. Für Error.cause
wird der Vergleich asymmetrisch durchgeführt:
// Erfolg
expect(new Error('hi', { cause: 'x' })).toEqual(new Error('hi'));
// Fehler
expect(new Error('hi')).toEqual(new Error('hi', { cause: 'x' }));
Um zu testen, ob etwas geworfen wurde, verwenden Sie die Assertion toThrowError
.
toStrictEqual
- Typ:
(received: any) => Awaitable<void>
toStrictEqual
bestätigt, ob der tatsächliche Wert dem empfangenen entspricht oder dieselbe Struktur hat, wenn es sich um ein Objekt handelt (vergleicht sie rekursiv), und vom selben Typ ist.
Unterschiede zu .toEqual
:
- Schlüssel mit
undefined
-Eigenschaften werden geprüft. Z.B.{a: undefined, b: 2}
stimmt nicht mit{b: 2}
überein, wenn.toStrictEqual
verwendet wird. - Die Spärlichkeit von Arrays wird geprüft. Z.B.
[, 1]
stimmt nicht mit[undefined, 1]
überein, wenn.toStrictEqual
verwendet wird. - Objekttypen werden auf Gleichheit geprüft. Z.B. Eine Klasseninstanz mit den Feldern
a
undb
entspricht nicht einem Literalobjekt mit den Felderna
undb
.
import { expect, test } from 'vitest';
class Stock {
constructor(type) {
this.type = type;
}
}
test('strukturell gleich, aber semantisch unterschiedlich', () => {
expect(new Stock('apples')).toEqual({ type: 'apples' });
expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' });
});
toContain
- Typ:
(received: string) => Awaitable<void>
toContain
bestätigt, ob der tatsächliche Wert in einem Array enthalten ist. toContain
kann auch prüfen, ob ein String ein Substring eines anderen Strings ist. Wenn Sie Tests in einer browserähnlichen Umgebung ausführen, kann diese Assertion auch prüfen, ob eine Klasse in einer classList
enthalten ist oder ein Element in einem anderen Element enthalten ist.
import { expect, test } from 'vitest';
import { getAllFruits } from './stocks.js';
test('die Fruchtliste enthält Orange', () => {
expect(getAllFruits()).toContain('orange');
const element = document.querySelector('#el');
// Element hat eine Klasse
expect(element.classList).toContain('flex');
// Element ist in einem anderen enthalten
expect(document.querySelector('#wrapper')).toContain(element);
});
toContainEqual
- Typ:
(received: any) => Awaitable<void>
toContainEqual
bestätigt, ob ein Element mit einer bestimmten Struktur und Werten in einem Array enthalten ist. Es funktioniert intern wie toEqual
für jedes Element.
import { expect, test } from 'vitest';
import { getFruitStock } from './stocks.js';
test('Apfel verfügbar', () => {
expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 });
});
toHaveLength
- Typ:
(received: number) => Awaitable<void>
toHaveLength
bestätigt, ob ein Objekt eine .length
-Eigenschaft hat und diese auf einen bestimmten numerischen Wert gesetzt ist.
import { expect, test } from 'vitest';
test('toHaveLength', () => {
expect('abc').toHaveLength(3);
expect([1, 2, 3]).toHaveLength(3);
expect('').not.toHaveLength(3); // hat keine .length von 3
expect({ length: 3 }).toHaveLength(3);
});
toHaveProperty
- Typ:
(key: any, received?: any) => Awaitable<void>
toHaveProperty
bestätigt, ob eine Eigenschaft am angegebenen Referenzschlüssel key
für ein Objekt existiert.
Sie können auch ein optionales Wertargument angeben, das auch als tiefe Gleichheit bekannt ist, ähnlich dem toEqual
-Matcher, um den empfangenen Eigenschaftswert zu vergleichen.
import { expect, test } from 'vitest';
const invoice = {
isActive: true,
'P.O': '12345',
customer: {
first_name: 'John',
last_name: 'Doe',
location: 'China',
},
total_amount: 5000,
items: [
{
type: 'apples',
quantity: 10,
},
{
type: 'oranges',
quantity: 5,
},
],
};
test('John Doe Rechnung', () => {
expect(invoice).toHaveProperty('isActive'); // bestätigt, dass der Schlüssel existiert
expect(invoice).toHaveProperty('total_amount', 5000); // bestätigt, dass der Schlüssel existiert und der Wert gleich ist
expect(invoice).not.toHaveProperty('account'); // bestätigt, dass dieser Schlüssel nicht existiert
// Tiefe Referenzierung mit Punktnotation
expect(invoice).toHaveProperty('customer.first_name');
expect(invoice).toHaveProperty('customer.last_name', 'Doe');
expect(invoice).not.toHaveProperty('customer.location', 'India');
// Tiefe Referenzierung mit einem Array, das den Schlüssel enthält
expect(invoice).toHaveProperty('items[0].type', 'apples');
expect(invoice).toHaveProperty('items.0.type', 'apples'); // Punktnotation funktioniert auch
// Tiefe Referenzierung mit einem Array, das den Schlüsselpfad enthält
expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples');
expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // String-Notation funktioniert auch
// Umschließen Sie Ihren Schlüssel in einem Array, um zu vermeiden, dass der Schlüssel als tiefe Referenz geparst wird
expect(invoice).toHaveProperty(['P.O'], '12345');
});
toMatch
- Typ:
(received: string | regexp) => Awaitable<void>
toMatch
bestätigt, ob ein String einem regulären Ausdruck oder einem String entspricht.
import { expect, test } from 'vitest';
test('Top-Früchte', () => {
expect('Top-Früchte sind Apfel, Orange und Traube').toMatch(/apple/);
expect('Apfelfrüchte').toMatch('Frucht'); // toMatch akzeptiert auch einen String
});
toMatchObject
- Typ:
(received: object | array) => Awaitable<void>
toMatchObject
bestätigt, ob ein Objekt einer Teilmenge der Eigenschaften eines Objekts entspricht.
Sie können auch ein Array von Objekten übergeben. Dies ist nützlich, wenn Sie prüfen möchten, ob zwei Arrays die gleiche Anzahl von Elementen haben, im Gegensatz zu arrayContaining
, das zusätzliche Elemente im empfangenen Array zulässt.
import { expect, test } from 'vitest';
const johnInvoice = {
isActive: true,
customer: {
first_name: 'John',
last_name: 'Doe',
location: 'China',
},
total_amount: 5000,
items: [
{
type: 'apples',
quantity: 10,
},
{
type: 'oranges',
quantity: 5,
},
],
};
const johnDetails = {
customer: {
first_name: 'John',
last_name: 'Doe',
location: 'China',
},
};
test('Rechnung enthält Johns persönliche Daten', () => {
expect(johnInvoice).toMatchObject(johnDetails);
});
test('die Anzahl der Elemente muss exakt übereinstimmen', () => {
// Bestätigen, dass ein Array von Objekten übereinstimmt
expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([
{ foo: 'bar' },
{ baz: 1 },
]);
});
toThrowError
Typ:
(received: any) => Awaitable<void>
Alias:
toThrow
toThrowError
bestätigt, ob eine Funktion einen Fehler wirft, wenn sie aufgerufen wird.
Sie können ein optionales Argument angeben, um zu testen, ob ein bestimmter Fehler geworfen wird:
RegExp
: Fehlermeldung entspricht dem Musterstring
: Fehlermeldung enthält den SubstringError
,AsymmetricMatcher
: Vergleich mit einem empfangenen Objekt ähnlichtoEqual(received)
TIP
Sie müssen den Code in eine Funktion einschließen, da der Fehler andernfalls nicht abgefangen wird und der Test fehlschlägt.
Dies gilt nicht für asynchrone Aufrufe, da rejects das Promise korrekt auflöst:
test('expect rejects toThrow', async ({ expect }) => {
const promise = Promise.reject(new Error('Test'));
await expect(promise).rejects.toThrowError();
});
Wenn wir zum Beispiel testen möchten, dass getFruitStock('pineapples')
einen Fehler wirft, könnten wir schreiben:
import { expect, test } from 'vitest';
function getFruitStock(type: string) {
if (type === 'pineapples') {
throw new Error('Ananas sind nicht auf Lager');
}
// Mache andere Dinge
}
test('wirft bei Ananas', () => {
// Teste, dass die Fehlermeldung irgendwo "stock" enthält: diese sind äquivalent
expect(() => getFruitStock('pineapples')).toThrowError(/stock/);
expect(() => getFruitStock('pineapples')).toThrowError('stock');
// Teste die exakte Fehlermeldung
expect(() => getFruitStock('pineapples')).toThrowError(
/^Ananas sind nicht auf Lager$/
);
expect(() => getFruitStock('pineapples')).toThrowError(
new Error('Ananas sind nicht auf Lager')
);
expect(() => getFruitStock('pineapples')).toThrowError(
expect.objectContaining({
message: 'Ananas sind nicht auf Lager',
})
);
});
TIP
Um asynchrone Funktionen zu testen, verwenden Sie sie in Kombination mit rejects.
function getAsyncFruitStock() {
return Promise.reject(new Error('empty'));
}
test('wirft bei Ananas', async () => {
await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty');
});
toMatchSnapshot
- Typ:
<T>(shape?: Partial<T> | string, hint?: string) => void
Dies stellt sicher, dass ein Wert mit dem neuesten Snapshot übereinstimmt.
Sie können ein optionales hint
-String-Argument angeben, das an den Testnamen angehängt wird. Obwohl Vitest immer eine Zahl am Ende eines Snapshot-Namens hinzufügt, können kurze, beschreibende Hinweise nützlicher sein als Zahlen, um mehrere Snapshots in einem einzelnen it
- oder test
-Block zu unterscheiden. Vitest sortiert Snapshots nach Namen in der entsprechenden .snap
-Datei.
TIP
Wenn ein Snapshot nicht übereinstimmt und zum Fehlschlagen des Tests führt, können Sie, wenn die Nichtübereinstimmung erwartet wird, die Taste u
drücken, um den Snapshot einmal zu aktualisieren. Oder Sie können die CLI-Optionen -u
oder --update
übergeben, damit Vitest die Tests immer aktualisiert.
import { expect, test } from 'vitest';
test('stimmt mit Snapshot überein', () => {
const data = { foo: new Set(['bar', 'snapshot']) };
expect(data).toMatchSnapshot();
});
Sie können auch eine Form eines Objekts angeben, wenn Sie nur die Form eines Objekts testen und es nicht zu 100% kompatibel sein muss:
import { expect, test } from 'vitest';
test('stimmt mit Snapshot überein', () => {
const data = { foo: new Set(['bar', 'snapshot']) };
expect(data).toMatchSnapshot({ foo: expect.any(Set) });
});
toMatchInlineSnapshot
- Typ:
<T>(shape?: Partial<T> | string, snapshot?: string, hint?: string) => void
Dies stellt sicher, dass ein Wert mit dem aktuellsten Snapshot übereinstimmt.
Vitest fügt das inlineSnapshot
-String-Argument zum Matcher in der Testdatei hinzu und aktualisiert es (anstelle einer externen .snap
-Datei).
import { expect, test } from 'vitest';
test('stimmt mit Inline-Snapshot überein', () => {
const data = { foo: new Set(['bar', 'snapshot']) };
// Vitest aktualisiert den folgenden Inhalt beim Aktualisieren des Snapshots
expect(data).toMatchInlineSnapshot(`
{
"foo": Set {
"bar",
"snapshot",
},
}
`);
});
Sie können auch eine Form eines Objekts angeben, wenn Sie nur die Form eines Objekts testen und es nicht zu 100% kompatibel sein muss:
import { expect, test } from 'vitest';
test('stimmt mit Snapshot überein', () => {
const data = { foo: new Set(['bar', 'snapshot']) };
expect(data).toMatchInlineSnapshot(
{ foo: expect.any(Set) },
`
{
"foo": Any<Set>,
}
`
);
});
toMatchFileSnapshot
- Typ:
<T>(filepath: string, hint?: string) => Promise<void>
Vergleicht oder aktualisiert den Snapshot mit dem Inhalt einer explizit angegebenen Datei (anstelle der .snap
-Datei).
import { expect, it } from 'vitest';
it('rendert grundlegend', async () => {
const result = renderHTML(h('div', { class: 'foo' }));
await expect(result).toMatchFileSnapshot('./test/basic.output.html');
});
Beachten Sie, dass Sie await
mit toMatchFileSnapshot()
verwenden müssen, da Dateisystemoperationen asynchron ablaufen. Wenn await
nicht verwendet wird, interpretiert Vitest es wie expect.soft
, was bedeutet, dass der Code nach der Anweisung weiter ausgeführt wird, selbst wenn der Snapshot nicht übereinstimmt. Nachdem der Test abgeschlossen ist, prüft Vitest den Snapshot und schlägt fehl, wenn eine Nichtübereinstimmung vorliegt.
toThrowErrorMatchingSnapshot
- Typ:
(hint?: string) => void
Dasselbe wie toMatchSnapshot
, erwartet aber denselben Wert wie toThrowError
.
toThrowErrorMatchingInlineSnapshot
- Typ:
(snapshot?: string, hint?: string) => void
Dasselbe wie toMatchInlineSnapshot
, erwartet aber denselben Wert wie toThrowError
.
toHaveBeenCalled
- Typ:
() => Awaitable<void>
Diese Assertion ist nützlich, um zu testen, ob eine Funktion aufgerufen wurde. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('Spy-Funktion', () => {
const buySpy = vi.spyOn(market, 'buy');
expect(buySpy).not.toHaveBeenCalled();
market.buy('Äpfel', 10);
expect(buySpy).toHaveBeenCalled();
});
toHaveBeenCalledTimes
- Typ:
(amount: number) => Awaitable<void>
Diese Assertion prüft, ob eine Funktion eine bestimmte Anzahl an Malen aufgerufen wurde. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('Spy-Funktion zweimal aufgerufen', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('Äpfel', 10);
market.buy('Äpfel', 20);
expect(buySpy).toHaveBeenCalledTimes(2);
});
toHaveBeenCalledWith
- Typ:
(...args: any[]) => Awaitable<void>
Diese Assertion prüft, ob eine Funktion mindestens einmal mit den angegebenen Parametern aufgerufen wurde. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('Spy-Funktion', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('Äpfel', 10);
market.buy('Äpfel', 20);
expect(buySpy).toHaveBeenCalledWith('Äpfel', 10);
expect(buySpy).toHaveBeenCalledWith('Äpfel', 20);
});
toHaveBeenCalledBefore 3.0.0+
- Typ:
(mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>
Diese Assertion prüft, ob ein Mock
vor einem anderen Mock
aufgerufen wurde.
test('ruft mock1 vor mock2 auf', () => {
const mock1 = vi.fn();
const mock2 = vi.fn();
mock1();
mock2();
mock1();
expect(mock1).toHaveBeenCalledBefore(mock2);
});
toHaveBeenCalledAfter 3.0.0+
- Typ:
(mock: MockInstance, failIfNoFirstInvocation?: boolean) => Awaitable<void>
Diese Assertion prüft, ob ein Mock
nach einem anderen Mock
aufgerufen wurde.
test('ruft mock1 nach mock2 auf', () => {
const mock1 = vi.fn();
const mock2 = vi.fn();
mock2();
mock1();
mock2();
expect(mock1).toHaveBeenCalledAfter(mock2);
});
toHaveBeenCalledExactlyOnceWith 3.0.0+
- Typ:
(...args: any[]) => Awaitable<void>
Diese Assertion prüft, ob eine Funktion genau einmal und mit den angegebenen Parametern aufgerufen wurde. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('Spy-Funktion', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('Äpfel', 10);
expect(buySpy).toHaveBeenCalledExactlyOnceWith('Äpfel', 10);
});
toHaveBeenLastCalledWith
- Typ:
(...args: any[]) => Awaitable<void>
Diese Assertion prüft, ob eine Funktion beim letzten Aufruf mit bestimmten Parametern aufgerufen wurde. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('Spy-Funktion', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('Äpfel', 10);
market.buy('Äpfel', 20);
expect(buySpy).not.toHaveBeenLastCalledWith('Äpfel', 10);
expect(buySpy).toHaveBeenLastCalledWith('Äpfel', 20);
});
toHaveBeenNthCalledWith
- Typ:
(time: number, ...args: any[]) => Awaitable<void>
Diese Assertion prüft, ob eine Funktion zu einem bestimmten Zeitpunkt mit bestimmten Parametern aufgerufen wurde. Die Zählung beginnt bei 1. Um den zweiten Eintrag zu prüfen, schreibt man also .toHaveBeenNthCalledWith(2, ...)
.
Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('erster Aufruf der Spy-Funktion mit den richtigen Parametern', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('Äpfel', 10);
market.buy('Äpfel', 20);
expect(buySpy).toHaveBeenNthCalledWith(1, 'Äpfel', 10);
});
toHaveReturned
- Typ:
() => Awaitable<void>
Diese Assertion prüft, ob eine Funktion mindestens einmal erfolgreich einen Wert zurückgegeben hat (d.h. ohne einen Fehler auszulösen). Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
function getApplesPrice(amount: number) {
const PRICE = 10;
return amount * PRICE;
}
test('Spy-Funktion hat einen Wert zurückgegeben', () => {
const getPriceSpy = vi.fn(getApplesPrice);
const price = getPriceSpy(10);
expect(price).toBe(100);
expect(getPriceSpy).toHaveReturned();
});
toHaveReturnedTimes
- Typ:
(amount: number) => Awaitable<void>
Diese Assertion prüft, ob eine Funktion genau eine bestimmte Anzahl von Malen erfolgreich einen Wert zurückgegeben hat (d.h. ohne einen Fehler auszulösen). Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion gibt zweimal einen Wert zurück', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('Äpfel');
sell('Bananen');
expect(sell).toHaveReturnedTimes(2);
});
toHaveReturnedWith
- Typ:
(returnValue: any) => Awaitable<void>
Sie können diese Assertion aufrufen, um zu prüfen, ob eine Funktion mindestens einmal erfolgreich einen Wert mit den angegebenen Parametern zurückgegeben hat. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion gibt ein Produkt zurück', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('Äpfel');
expect(sell).toHaveReturnedWith({ product: 'apples' });
});
toHaveLastReturnedWith
- Typ:
(returnValue: any) => Awaitable<void>
Sie können diese Assertion aufrufen, um zu prüfen, ob eine Funktion beim letzten Aufruf erfolgreich einen bestimmten Wert zurückgegeben hat. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion gibt bei letztem Aufruf Bananen zurück', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('Äpfel');
sell('Bananen');
expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});
toHaveNthReturnedWith
- Typ:
(time: number, returnValue: any) => Awaitable<void>
Sie können diese Assertion aufrufen, um zu prüfen, ob eine Funktion bei einem spezifischen Aufruf erfolgreich einen Wert mit bestimmten Parametern zurückgegeben hat. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion gibt bei zweitem Aufruf Bananen zurück', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('Äpfel');
sell('Bananen');
expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' });
});
toHaveResolved
- Typ:
() => Awaitable<void>
Diese Assertion prüft, ob eine Funktion mindestens einmal erfolgreich einen Wert aufgelöst hat (d.h. nicht abgelehnt wurde). Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
Wenn die Funktion ein Promise zurückgegeben hat, dieses aber noch nicht erfüllt wurde, schlägt dies fehl.
import { expect, test, vi } from 'vitest';
import db from './db/apples.js';
async function getApplesPrice(amount: number) {
return amount * (await db.get('price'));
}
test('Spy-Funktion hat einen Wert aufgelöst', async () => {
const getPriceSpy = vi.fn(getApplesPrice);
const price = await getPriceSpy(10);
expect(price).toBe(100);
expect(getPriceSpy).toHaveResolved();
});
toHaveResolvedTimes
- Typ:
(amount: number) => Awaitable<void>
Diese Assertion prüft, ob eine Funktion genau eine bestimmte Anzahl von Malen erfolgreich einen Wert aufgelöst hat (d.h. nicht abgelehnt wurde). Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
Hierbei werden nur aufgelöste Promises gezählt. Wenn die Funktion ein Promise zurückgegeben hat, dieses aber noch nicht erfüllt wurde, wird es nicht gezählt.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion hat zweimal einen Wert aufgelöst', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('Äpfel');
await sell('Bananen');
expect(sell).toHaveResolvedTimes(2);
});
toHaveResolvedWith
- Typ:
(returnValue: any) => Awaitable<void>
Sie können diese Assertion aufrufen, um zu prüfen, ob eine Funktion mindestens einmal erfolgreich einen bestimmten Wert aufgelöst hat. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
Wenn die Funktion ein Promise zurückgegeben hat, dieses aber noch nicht erfüllt wurde, schlägt dies fehl.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion hat ein Produkt aufgelöst', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('Äpfel');
expect(sell).toHaveResolvedWith({ product: 'apples' });
});
toHaveLastResolvedWith
- Typ:
(returnValue: any) => Awaitable<void>
Sie können diese Assertion aufrufen, um zu prüfen, ob eine Funktion bei ihrem letzten Aufruf erfolgreich einen bestimmten Wert aufgelöst hat. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
Wenn die Funktion ein Promise zurückgegeben hat, dieses aber noch nicht erfüllt wurde, schlägt dies fehl.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion löst bei letztem Aufruf Bananen auf', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('Äpfel');
await sell('Bananen');
expect(sell).toHaveLastResolvedWith({ product: 'bananas' });
});
toHaveNthResolvedWith
- Typ:
(time: number, returnValue: any) => Awaitable<void>
Sie können diese Assertion aufrufen, um zu prüfen, ob eine Funktion bei einem spezifischen Aufruf erfolgreich einen bestimmten Wert aufgelöst hat. Voraussetzung ist, dass eine Spy-Funktion an expect
übergeben wird.
Wenn die Funktion ein Promise zurückgegeben hat, dieses aber noch nicht erfüllt wurde, schlägt dies fehl.
import { expect, test, vi } from 'vitest';
test('Spy-Funktion gibt bei zweitem Aufruf Bananen zurück', async () => {
const sell = vi.fn((product: string) => Promise.resolve({ product }));
await sell('Äpfel');
await sell('Bananen');
expect(sell).toHaveNthResolvedWith(2, { product: 'bananas' });
});
toSatisfy
- Typ:
(predicate: (value: any) => boolean) => Awaitable<void>
Diese Assertion prüft, ob ein Wert ein bestimmtes Prädikat erfüllt.
import { describe, expect, it } from 'vitest';
const isOdd = (value: number) => value % 2 !== 0;
describe('toSatisfy()', () => {
it('besteht mit 0', () => {
expect(1).toSatisfy(isOdd);
});
it('besteht mit Negation', () => {
expect(2).not.toSatisfy(isOdd);
});
});
resolves
- Typ:
Promisify<Assertions>
resolves
soll redundanten Code beim Bestätigen von asynchronem Code entfernen. Verwenden Sie es, um Werte aus dem ausstehenden Promise aufzulösen und ihren Wert mit den üblichen Assertions zu bestätigen. Wenn das Promise fehlschlägt, schlägt die Assertion fehl.
Es gibt dasselbe Assertions
-Objekt zurück, aber alle Matcher geben jetzt Promise
zurück, sodass Sie asynchron darauf warten müssen. Ist auch kompatibel mit chai
-Assertions.
Wenn Sie beispielsweise eine Funktion haben, die einen API-Aufruf macht und Daten zurückgibt, können Sie diesen Code verwenden, um ihren Rückgabewert zu bestätigen:
import { expect, test } from 'vitest';
async function buyApples() {
return fetch('/buy/apples').then(r => r.json());
}
test('buyApples gibt neue Bestands-ID zurück', async () => {
// toEqual gibt jetzt ein Promise zurück, daher MÜSSEN Sie es awaiten
await expect(buyApples()).resolves.toEqual({ id: 1 }); // jest API
await expect(buyApples()).resolves.to.equal({ id: 1 }); // chai API
});
WARNING
Wenn die Assertion nicht asynchron abgewartet wird, erhalten Sie einen falsch-positiven Test, der jedes Mal besteht. Um sicherzustellen, dass Assertions wirklich aufgerufen werden, können Sie expect.assertions(number)
verwenden.
Seit Vitest 3 zeigt Vitest am Ende des Tests eine Warnung an, wenn eine Methode nicht asynchron abgewartet wird. In Vitest 4 wird der Test als "fehlgeschlagen" markiert, wenn die Assertion nicht asynchron abgewartet wird.
rejects
- Typ:
Promisify<Assertions>
rejects
soll redundanten Code beim Bestätigen von asynchronem Code entfernen. Verwenden Sie es, um den Ablehnungsgrund des Promises zu extrahieren und seinen Wert mit den üblichen Assertions zu bestätigen. Wenn das Promise erfolgreich erfüllt wird, schlägt die Assertion fehl.
Es gibt dasselbe Assertions
-Objekt zurück, aber alle Matcher geben jetzt Promise
zurück, sodass Sie asynchron darauf warten müssen. Ist auch kompatibel mit chai
-Assertions.
Wenn Sie beispielsweise eine Funktion haben, die fehlschlägt, wenn Sie sie aufrufen, können Sie diesen Code verwenden, um den Grund zu bestätigen:
import { expect, test } from 'vitest';
async function buyApples(id) {
if (!id) {
throw new Error('keine ID');
}
}
test('buyApples wirft einen Fehler, wenn keine ID angegeben wird', async () => {
// toThrow gibt jetzt ein Promise zurück, daher MÜSSEN Sie es awaiten
await expect(buyApples()).rejects.toThrow('keine ID');
});
WARNING
Wenn die Assertion nicht asynchron abgewartet wird, erhalten Sie einen falsch-positiven Test, der jedes Mal besteht. Um sicherzustellen, dass Assertions wirklich aufgerufen wurden, können Sie expect.assertions(number)
verwenden.
Seit Vitest 3 zeigt Vitest am Ende des Tests eine Warnung an, wenn eine Methode nicht asynchron abgewartet wird. In Vitest 4 wird der Test als "fehlgeschlagen" markiert, wenn die Assertion nicht asynchron abgewartet wird.
expect.assertions
- Typ:
(count: number) => void
Nachdem der Test bestanden oder fehlgeschlagen ist, wird überprüft, ob eine bestimmte Anzahl von Assertions während eines Tests aufgerufen wurde. Ein nützlicher Anwendungsfall ist es, zu prüfen, ob ein asynchroner Code aufgerufen wurde.
Wenn wir beispielsweise eine Funktion haben, die asynchron zwei Matcher aufruft, können wir bestätigen, dass sie tatsächlich aufgerufen wurden.
import { expect, test } from 'vitest';
async function doAsync(...cbs) {
await Promise.all(cbs.map((cb, index) => cb({ index })));
}
test('alle Assertions werden aufgerufen', async () => {
expect.assertions(2);
function callback1(data) {
expect(data).toBeTruthy();
}
function callback2(data) {
expect(data).toBeTruthy();
}
await doAsync(callback1, callback2);
});
WARNING
Bei der Verwendung von assertions
mit asynchronen, parallelen Tests muss expect
aus dem lokalen Testkontext verwendet werden, um sicherzustellen, dass der korrekte Test identifiziert wird.
expect.hasAssertions
- Typ:
() => void
Nachdem der Test bestanden oder fehlgeschlagen ist, wird überprüft, ob mindestens eine Assertion während eines Tests aufgerufen wurde. Ein nützlicher Anwendungsfall ist es, zu prüfen, ob ein asynchroner Code aufgerufen wurde.
Wenn Sie beispielsweise einen Code haben, der einen Callback aufruft, können wir eine Assertion innerhalb eines Callbacks machen, aber der Test wird immer bestanden, wenn wir nicht prüfen, ob eine Assertion aufgerufen wurde.
import { expect, test } from 'vitest';
import { db } from './db.js';
const cbs = [];
function onSelect(cb) {
cbs.push(cb);
}
// nach der Auswahl aus der DB rufen wir alle Callbacks auf
function select(id) {
return db.select({ id }).then(data => {
return Promise.all(cbs.map(cb => cb(data)));
});
}
test('Callback wurde aufgerufen', async () => {
expect.hasAssertions();
onSelect(data => {
// sollte bei Auswahl aufgerufen werden
expect(data).toBeTruthy();
});
// wenn nicht asynchron abgewartet, schlägt der Test fehl
// wenn expect.hasAssertions() nicht verwendet wird, besteht der Test
await select(3);
});
expect.unreachable
- Typ:
(message?: string) => never
Diese Methode wird verwendet, um sicherzustellen, dass eine bestimmte Codezeile niemals erreicht wird.
Wenn wir zum Beispiel testen möchten, dass build()
einen Fehler wirft, weil die Zielverzeichnisse keinen src
-Ordner enthalten, und jeden Fehler separat behandeln möchten, könnten wir dies tun:
import { expect, test } from 'vitest';
async function build(dir) {
if (dir.includes('no-src')) {
throw new Error(`${dir}/src existiert nicht`);
}
}
const errorDirs = [
'no-src-folder',
// ...
];
test.each(errorDirs)('Build schlägt fehl mit "%s"', async dir => {
try {
await build(dir);
expect.unreachable('Sollte den Build nicht bestehen');
} catch (err: any) {
expect(err).toBeInstanceOf(Error);
expect(err.stack).toContain('build');
switch (dir) {
case 'no-src-folder':
expect(err.message).toBe(`${dir}/src existiert nicht`);
break;
default:
// um alle Fehlertests zu erschöpfen
expect.unreachable('Alle Fehlertests müssen behandelt werden');
break;
}
}
});
expect.anything
- Typ:
() => any
Dieser asymmetrische Matcher gibt in Verbindung mit einem Gleichheitscheck immer true
zurück. Nützlich, wenn Sie nur sicherstellen möchten, dass die Eigenschaft vorhanden ist.
import { expect, test } from 'vitest';
test('Objekt hat den Schlüssel "apples"', () => {
expect({ apples: 22 }).toEqual({ apples: expect.anything() });
});
expect.any
- Typ:
(constructor: unknown) => any
Dieser asymmetrische Matcher gibt in Verbindung mit einem Gleichheitscheck nur dann true
zurück, wenn der Wert eine Instanz eines angegebenen Konstruktors ist. Nützlich, wenn Sie einen Wert haben, der jedes Mal generiert wird, und Sie nur wissen möchten, dass er einen geeigneten Typ hat.
import { expect, test } from 'vitest';
import { generateId } from './generators.js';
test('"id" ist eine Zahl', () => {
expect({ id: generateId() }).toEqual({ id: expect.any(Number) });
});
expect.closeTo
- Typ:
(expected: any, precision?: number) => any
expect.closeTo
ist nützlich beim Vergleichen von Gleitkommazahlen in Objekteigenschaften oder Array-Elementen. Wenn Sie eine Zahl vergleichen müssen, verwenden Sie stattdessen .toBeCloseTo
.
Das optionale precision
-Argument begrenzt die Anzahl der zu berücksichtigenden Nachkommastellen. Für den Standardwert 2
gilt das Testkriterium Math.abs(expected - received) < 0.005 (d.h. 10 ** -2 / 2)
.
Zum Beispiel besteht dieser Test mit einer Genauigkeit von 5 Ziffern:
test('Gleitkommazahlen in Objekteigenschaften vergleichen', () => {
expect({
title: '0.1 + 0.2',
sum: 0.1 + 0.2,
}).toEqual({
title: '0.1 + 0.2',
sum: expect.closeTo(0.3, 5),
});
});
expect.arrayContaining
- Typ:
<T>(expected: T[]) => any
In Verbindung mit einem Gleichheitscheck gibt dieser asymmetrische Matcher true
zurück, wenn der Wert ein Array ist und die angegebenen Elemente enthält.
import { expect, test } from 'vitest';
test('Korb enthält Fuji', () => {
const basket = {
varieties: ['Empire', 'Fuji', 'Gala'],
count: 3,
};
expect(basket).toEqual({
count: 3,
varieties: expect.arrayContaining(['Fuji']),
});
});
TIP
Sie können expect.not
mit diesem Matcher verwenden, um den erwarteten Wert zu negieren.
expect.objectContaining
- Typ:
(expected: any) => any
In Verbindung mit einem Gleichheitscheck gibt dieser asymmetrische Matcher true
zurück, wenn der Wert eine ähnliche Form hat.
import { expect, test } from 'vitest';
test('Korb hat Empire-Äpfel', () => {
const basket = {
varieties: [
{
name: 'Empire',
count: 1,
},
],
};
expect(basket).toEqual({
varieties: [expect.objectContaining({ name: 'Empire' })],
});
});
TIP
Sie können expect.not
mit diesem Matcher verwenden, um den erwarteten Wert zu negieren.
expect.stringContaining
- Typ:
(expected: any) => any
In Verbindung mit einem Gleichheitscheck gibt dieser asymmetrische Matcher true
zurück, wenn der Wert ein String ist und einen angegebenen Substring enthält.
import { expect, test } from 'vitest';
test('Sorte enthält "Emp" im Namen', () => {
const variety = {
name: 'Empire',
count: 1,
};
expect(variety).toEqual({
name: expect.stringContaining('Emp'),
count: 1,
});
});
TIP
Sie können expect.not
mit diesem Matcher verwenden, um den erwarteten Wert zu negieren.
expect.stringMatching
- Typ:
(expected: any) => any
In Verbindung mit einem Gleichheitscheck gibt dieser asymmetrische Matcher true
zurück, wenn der Wert ein String ist und einen angegebenen Substring enthält oder wenn der String einem regulären Ausdruck entspricht.
import { expect, test } from 'vitest';
test('Sorte endet mit "re"', () => {
const variety = {
name: 'Empire',
count: 1,
};
expect(variety).toEqual({
name: expect.stringMatching(/re$/),
count: 1,
});
});
TIP
Sie können expect.not
mit diesem Matcher verwenden, um den erwarteten Wert zu negieren.
expect.addSnapshotSerializer
- Typ:
(plugin: PrettyFormatPlugin) => void
Diese Methode fügt benutzerdefinierte Serializer hinzu, die beim Erstellen eines Snapshots zum Einsatz kommen. Dies ist eine fortgeschrittene Funktion – weitere Informationen finden Sie im Leitfaden zu benutzerdefinierten Serializern.
Wenn Sie benutzerdefinierte Serializer hinzufügen, ist es ratsam, diese Methode innerhalb von setupFiles
aufzurufen. Dies betrifft jeden Snapshot.
TIP
Wenn Sie zuvor Vue CLI mit Jest verwendet haben, möchten Sie möglicherweise jest-serializer-vue installieren. Andernfalls werden Ihre Snapshots in einen String gewickelt, wodurch "
maskiert wird.
expect.extend
- Typ:
(matchers: MatchersObject) => void
Sie können Standard-Matcher um eigene Matcher erweitern. Diese Funktion wird verwendet, um das Matcher-Objekt um benutzerdefinierte Matcher zu erweitern.
Wenn Sie Matcher so definieren, erstellen Sie auch asymmetrische Matcher, die wie expect.stringContaining
verwendet werden können.
import { expect, test } from 'vitest';
test('benutzerdefinierte Matcher', () => {
expect.extend({
toBeFoo: (received, expected) => {
if (received !== 'foo') {
return {
message: () => `erwartet, dass ${received} foo ist`,
pass: false,
};
}
},
});
expect('foo').toBeFoo();
expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() });
});
TIP
Wenn Ihre Matcher in jedem Test verfügbar sein sollen, ist es ratsam, diese Methode innerhalb von setupFiles
aufzurufen.
Diese Funktion ist kompatibel mit Jests expect.extend
, daher funktioniert jede Bibliothek, die sie zum Erstellen benutzerdefinierter Matcher verwendet, mit Vitest.
Wenn Sie TypeScript verwenden, können Sie seit Vitest 0.31.0 die Standard-Assertion
-Schnittstelle in einer Ambient-Deklarationsdatei (z.B. vitest.d.ts
) mit dem folgenden Code erweitern:
interface CustomMatchers<R = unknown> {
toBeFoo: () => R;
}
declare module 'vitest' {
interface Assertion<T = any> extends CustomMatchers<T> {}
interface AsymmetricMatchersContaining extends CustomMatchers {}
}
WARNING
Vergessen Sie nicht, die Ambient-Deklarationsdatei in Ihre tsconfig.json
einzubinden.
TIP
Wenn Sie mehr wissen möchten, schauen Sie sich den Leitfaden zum Erweitern von Matchern an.
expect.addEqualityTesters
- Typ:
(tester: Array<Tester>) => void
Sie können diese Methode verwenden, um benutzerdefinierte Tester zu definieren, die von Matchern eingesetzt werden, um zu prüfen, ob zwei Objekte gleich sind. Sie ist kompatibel mit Jests expect.addEqualityTesters
.
import { expect, test } from 'vitest';
class AnagramComparator {
public word: string;
constructor(word: string) {
this.word = word;
}
equals(other: AnagramComparator): boolean {
const cleanStr1 = this.word.replace(/ /g, '').toLowerCase();
const cleanStr2 = other.word.replace(/ /g, '').toLowerCase();
const sortedStr1 = cleanStr1.split('').sort().join('');
const sortedStr2 = cleanStr2.split('').sort().join('');
return sortedStr1 === sortedStr2;
}
}
function isAnagramComparator(a: unknown): a is AnagramComparator {
return a instanceof AnagramComparator;
}
function areAnagramsEqual(a: unknown, b: unknown): boolean | undefined {
const isAAnagramComparator = isAnagramComparator(a);
const isBAnagramComparator = isAnagramComparator(b);
if (isAAnagramComparator && isBAnagramComparator) {
return a.equals(b);
} else if (isAAnagramComparator === isBAnagramComparator) {
return undefined;
} else {
return false;
}
}
expect.addEqualityTesters([areAnagramsEqual]);
test('benutzerdefinierter Gleichheitstester', () => {
expect(new AnagramComparator('listen')).toEqual(
new AnagramComparator('silent')
);
});