expect
Následující typy se používají v typových signaturách níže:
type Awaitable<T> = T | PromiseLike<T>;expect slouží k vytváření asercí. Aserce jsou v tomto kontextu funkce, které se volají k ověření tvrzení. Vitest ve výchozím nastavení poskytuje aserce chai a také aserce kompatibilní s Jest, které jsou postaveny na chai.
Například tento kód ověřuje, že hodnota input je rovna 2. Pokud tomu tak není, aserce vyvolá chybu a test selže.
import { expect } from 'vitest';
const input = Math.sqrt(4);
expect(input).to.equal(2); // chai API
expect(input).toBe(2); // jest APIZ technického hlediska tento příklad nepoužívá funkci test, takže v konzoli uvidíte chybu Node.js místo výstupu Vitest. Více informací o test naleznete v Referenci API Test.
expect lze také použít staticky pro přístup k funkcím matcherů, které jsou popsány dále, a dalším.
WARNING
expect nemá žádný vliv na testování typů, pokud výraz neobsahuje typovou chybu. Pro použití Vitest jako kontrolu typů použijte expectTypeOf nebo assertType.
soft
- Typ:
ExpectStatic & (actual: any) => Assertions
expect.soft funguje podobně jako expect, ale po neúspěšné aserci neukončí provádění testu, nýbrž pokračuje v běhu a označí selhání jako selhání testu. Všechny chyby, které se během testu vyskytnou, se zobrazí po dokončení testu.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // označí test jako neúspěšný a pokračuje v jeho provádění
expect.soft(1 + 2).toBe(4); // označí test jako neúspěšný a pokračuje v jeho provádění
});
// Na konci testu se zobrazí výše uvedené chyby.Lze jej také použít s expect. Pokud aserce expect selže, test se ukončí a zobrazí se všechny chyby.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // označí test jako neúspěšný a pokračuje v jeho provádění
expect(1 + 2).toBe(3); // selže a ukončí test, zobrazí se všechny předchozí chyby
expect.soft(1 + 2).toBe(4); // nebude vykonána
});WARNING
expect.soft lze použít pouze uvnitř funkce test.
not
Použití not neguje aserci. Například tento kód ověřuje, že hodnota input není rovna 2. Pokud se rovná, aserce vyvolá chybu a test selže.
import { expect, test } from 'vitest';
const input = Math.sqrt(16);
expect(input).not.to.equal(2); // chai API
expect(input).not.toBe(2); // jest APItoBe
Typ:
(value: any) => Awaitable<void>toBeslouží k ověření, zda se primitivní hodnoty rovnají nebo zda objekty sdílejí stejnou referenci. Je to ekvivalentní zápisuexpect(Object.is(3, 3)).toBe(true). Pokud objekty nejsou stejné, ale chcete zkontrolovat, zda jsou jejich struktury identické, použijtetoEqual.Například kód níže kontroluje, zda má obchodník 13 jablek.
tsimport { 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; // stejná reference expect(stock).toBe(refStock); });Vyhněte se používání
toBes čísly s plovoucí desetinnou čárkou. Protože je JavaScript zaokrouhluje,0.1 + 0.2není striktně0.3. Pro spolehlivé ověření čísel s plovoucí desetinnou čárkou použijte asercitoBeCloseTo.
toBeCloseTo
Typ:
(value: number, numDigits?: number) => Awaitable<void>Použijte
toBeCloseTok porovnání čísel s plovoucí desetinnou čárkou. Volitelný argumentnumDigitsurčuje počet číslic, které se mají kontrolovat za desetinnou čárkou. Například:tsimport { expect, test } from 'vitest'; test.fails('decimals are not equal in javascript', () => { expect(0.2 + 0.1).toBe(0.3); // 0.2 + 0.1 je 0.30000000000000004 }); test('decimals are rounded to 5 after the point', () => { // 0.2 + 0.1 je 0.30000 | "000000000004" odstraněno expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // nic z 0.30000000000000004 není odstraněno expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50); });
toBeDefined
Typ:
() => Awaitable<void>toBeDefinedověřuje, že hodnota není rovnaundefined. Užitečné je to například pro kontrolu, zda funkce něco vrátila.tsimport { expect, test } from 'vitest'; function getApples() { return 3; } test('function returned something', () => { expect(getApples()).toBeDefined(); });
toBeUndefined
Typ:
() => Awaitable<void>Opakem
toBeDefinedjetoBeUndefined, který ověřuje, že se hodnota rovnáundefined. Užitečné je to například pro kontrolu, zda funkce nic nevrátila.tsimport { expect, test } from 'vitest'; function getApplesFromStock(stock) { if (stock === 'Bill') return 13; } test("mary doesn't have a stock", () => { expect(getApplesFromStock('Mary')).toBeUndefined(); });
toBeTruthy
Typ:
() => Awaitable<void>toBeTruthyověřuje, že hodnota je true, když je převedena na boolean. Užitečné, pokud potřebujete pouze zjistit, zda lze hodnotu převést natrue.Například, když máte tento kód, nezajímáte se o návratovou hodnotu
stocks.getInfo- může to být složitý objekt, řetězec nebo cokoli jiného. Kód bude stále fungovat.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (stocks.getInfo('Bill')) stocks.sell('apples', 'Bill');Takže pokud chcete otestovat, že
stocks.getInfobude truthy, můžete napsat:tsimport { expect, test } from 'vitest'; import { Stocks } from './stocks.js'; const stocks = new Stocks(); test('if we know Bill stock, sell apples to him', () => { stocks.sync('Bill'); expect(stocks.getInfo('Bill')).toBeTruthy(); });V JavaScriptu je vše považováno za truthy hodnotu, kromě
false,0,'',null,undefinedaNaN.
toBeFalsy
Typ:
() => Awaitable<void>toBeFalsyověřuje, že hodnota je false, když je převedena na boolean. Užitečné, pokud potřebujete pouze zjistit, zda lze hodnotu převést nafalse.Například, pokud máte tento kód, nezáleží na konkrétní návratové hodnotě
stocks.stockFailed, důležité je, že vrací falsy hodnotu.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (!stocks.stockFailed('Bill')) stocks.sell('apples', 'Bill');Takže pokud chcete otestovat, že
stocks.stockFailedbude falsy, můžete napsat:tsimport { expect, test } from 'vitest'; import { Stocks } from './stocks.js'; const stocks = new Stocks(); test("if Bill stock hasn't failed, sell apples to him", () => { stocks.syncStocks('Bill'); expect(stocks.stockFailed('Bill')).toBeFalsy(); });V JavaScriptu je vše považováno za truthy hodnotu, kromě
false,0,'',null,undefinedaNaN.
toBeNull
Typ:
() => Awaitable<void>toBeNulljednoduše ověřuje, zda je hodnotanull. Alias pro.toBe(null).tsimport { expect, test } from 'vitest'; function apples() { return null; } test("we don't have apples", () => { expect(apples()).toBeNull(); });
toBeNaN
Typ:
() => Awaitable<void>toBeNaNjednoduše ověřuje, zda je hodnotaNaN. Alias pro.toBe(NaN).tsimport { expect, test } from 'vitest'; let i = 0; function getApplesCount() { i++; return i > 1 ? Number.NaN : i; } test('getApplesCount has some unusual side effects...', () => { expect(getApplesCount()).not.toBeNaN(); expect(getApplesCount()).toBeNaN(); });
toBeTypeOf
Typ:
(c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>toBeTypeOfověřuje, zda má skutečná hodnota typ, který byl přijat.tsimport { expect, test } from 'vitest'; const actual = 'stock'; test('stock is type of string', () => { expect(actual).toBeTypeOf('string'); });
toBeInstanceOf
Typ:
(c: any) => Awaitable<void>toBeInstanceOfověřuje, zda je skutečná hodnota instancí třídy, která byla přijata.tsimport { expect, test } from 'vitest'; import { Stocks } from './stocks.js'; const stocks = new Stocks(); test('stocks are instance of Stocks', () => { expect(stocks).toBeInstanceOf(Stocks); });
toBeGreaterThan
Typ:
(n: number | bigint) => Awaitable<void>toBeGreaterThanověřuje, zda je skutečná hodnota větší než hodnota, která byla přijata. Pokud jsou hodnoty stejné, test selže.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have more then 10 apples', () => { expect(getApples()).toBeGreaterThan(10); });
toBeGreaterThanOrEqual
Typ:
(n: number | bigint) => Awaitable<void>toBeGreaterThanOrEqualověřuje, zda je skutečná hodnota větší než přijatá hodnota nebo se jí rovná.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have 11 apples or more', () => { expect(getApples()).toBeGreaterThanOrEqual(11); });
toBeLessThan
Typ:
(n: number | bigint) => Awaitable<void>toBeLessThanověřuje, zda je skutečná hodnota menší než hodnota, která byla přijata. Pokud jsou hodnoty stejné, test selže.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have less then 20 apples', () => { expect(getApples()).toBeLessThan(20); });
toBeLessThanOrEqual
Typ:
(n: number | bigint) => Awaitable<void>toBeLessThanOrEqualověřuje, zda je skutečná hodnota menší než přijatá hodnota nebo se jí rovná.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have 11 apples or less', () => { expect(getApples()).toBeLessThanOrEqual(11); });
toEqual
Typ:
(received: any) => Awaitable<void>toEqualověřuje, zda se skutečná hodnota rovná hodnotě, která byla přijata, nebo má stejnou strukturu, pokud se jedná o objekt (porovnává je rekurzivně). Rozdíl mezitoEqualatoBemůžete vidět v tomto příkladu:tsimport { expect, test } from 'vitest'; const stockBill = { type: 'apples', count: 13, }; const stockMary = { type: 'apples', count: 13, }; test('stocks have the same properties', () => { expect(stockBill).toEqual(stockMary); }); test('stocks are not the same', () => { expect(stockBill).not.toBe(stockMary); });WARNING
Hloubkové porovnání se neprovádí pro objekty
Error. Chcete-li otestovat, zda byla vyhozena nějaká výjimka, použijte asercitoThrowError.
toStrictEqual
Typ:
(received: any) => Awaitable<void>toStrictEqualověřuje, zda se skutečná hodnota rovná hodnotě, která byla přijata, nebo má stejnou strukturu, pokud se jedná o objekt (porovnává je rekurzivně), a stejného typu.Rozdíly od
.toEqual:- Klíče s vlastnostmi
undefinedjsou kontrolovány. Např.{a: undefined, b: 2}se neshoduje s{b: 2}při použití.toStrictEqual. - Kontroluje se, zda je pole řídké. Např.
[, 1]se neshoduje s[undefined, 1]při použití.toStrictEqual. - Typy objektů jsou kontrolovány, zda jsou stejné. Např. Instance třídy s atributy
aabse nebude rovnat literálovému objektu s atributyaab.
tsimport { expect, test } from 'vitest'; class Stock { constructor(type) { this.type = type; } } test('structurally the same, but semantically different', () => { expect(new Stock('apples')).toEqual({ type: 'apples' }); expect(new Stock('apples')).not.toStrictEqual({ type: 'apples' }); });- Klíče s vlastnostmi
toContain
Typ:
(received: string) => Awaitable<void>toContainověřuje, zda je skutečná hodnota obsažena v poli.toContaintaké kontroluje, zda je jeden řetězec podřetězcem druhého.tsimport { expect, test } from 'vitest'; import { getAllFruits } from './stocks.js'; test('the fruit list contains orange', () => { expect(getAllFruits()).toContain('orange'); });
toContainEqual
Typ:
(received: any) => Awaitable<void>toContainEqualověřuje, zda je v poli obsažena položka se specifickou strukturou a hodnotami. Funguje jakotoEqualuvnitř pro každý prvek.tsimport { expect, test } from 'vitest'; import { getFruitStock } from './stocks.js'; test('apple available', () => { expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 }); });
toHaveLength
Typ:
(received: number) => Awaitable<void>toHaveLengthověřuje, zda má objekt vlastnost.lengtha zda je nastavena na určitou hodnotu.tsimport { expect, test } from 'vitest'; test('toHaveLength', () => { expect('abc').toHaveLength(3); expect([1, 2, 3]).toHaveLength(3); expect('').not.toHaveLength(3); // nemá vlastnost .length rovnou 3 expect({ length: 3 }).toHaveLength(3); });
toHaveProperty
Typ:
(key: any, received?: any) => Awaitable<void>toHavePropertyověřuje, zda objekt obsahuje vlastnost se zadaným klíčemkey.Můžete také zadat volitelný argument hodnoty, který slouží k hloubkovému porovnání (deep equality), podobně jako u matcheru
toEqual, pro porovnání hodnoty vlastnosti.tsimport { 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 Invoice', () => { expect(invoice).toHaveProperty('isActive'); // ověřte existenci klíče expect(invoice).toHaveProperty('total_amount', 5000); // ověřte existenci klíče a shodu hodnoty expect(invoice).not.toHaveProperty('account'); // ověřte, že klíč neexistuje // Hloubkové odkazování pomocí tečkové notace expect(invoice).toHaveProperty('customer.first_name'); expect(invoice).toHaveProperty('customer.last_name', 'Doe'); expect(invoice).not.toHaveProperty('customer.location', 'India'); // Hloubkové odkazování pomocí pole obsahujícího klíč expect(invoice).toHaveProperty('items[0].type', 'apples'); expect(invoice).toHaveProperty('items.0.type', 'apples'); // tečková notace také funguje // Hloubkové odkazování pomocí pole obsahujícího cestu ke klíči expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples'); expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // notace pomocí řetězců také funguje // Zabalte klíč do pole, abyste zabránili jeho parsování jako hloubkového odkazu expect(invoice).toHaveProperty(['P.O'], '12345'); });
toMatch
Typ:
(received: string | regexp) => Awaitable<void>toMatchověřuje, zda řetězec odpovídá regulárnímu výrazu nebo jinému řetězci.tsimport { expect, test } from 'vitest'; test('top fruits', () => { expect('top fruits include apple, orange and grape').toMatch(/apple/); expect('applefruits').toMatch('fruit'); // toMatch akceptuje i řetězec });
TIP
Pokud je hodnota v chybové zprávě příliš zkrácená, můžete zvýšit hodnotu chaiConfig.truncateThreshold v konfiguračním souboru.
toMatchObject
Typ:
(received: object | array) => Awaitable<void>toMatchObjectověřuje, zda objekt odpovídá podmnožině vlastností jiného objektu.Můžete také předat pole objektů. To je užitečné, pokud chcete zkontrolovat, zda se dvě pole shodují v počtu prvků, na rozdíl od
arrayContaining, které umožňuje další prvky v přijatém poli.tsimport { 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('invoice has john personal details', () => { expect(johnInvoice).toMatchObject(johnDetails); }); test('the number of elements must match exactly', () => { // Ověřte, že se pole objektů shoduje expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([ { foo: 'bar' }, { baz: 1 }, ]); });
toThrowError
Typ:
(received: any) => Awaitable<void>Alias:
toThrowtoThrowErrorověřuje, zda funkce při volání vyvolá chybu.Můžete zadat volitelný argument pro otestování, zda je vyvolána konkrétní chyba:
- regulární výraz: chybová zpráva odpovídá vzoru
- řetězec: chybová zpráva obsahuje podřetězec
TIP
Kód, který má vyvolat chybu, musíte zabalit do funkce, jinak nebude chyba zachycena a test selže.
Například, pokud chceme otestovat, zda
getFruitStock('pineapples')vyvolá chybu, můžeme napsat:tsimport { expect, test } from 'vitest'; function getFruitStock(type) { if (type === 'pineapples') throw new DiabetesError( 'Pineapples are not good for people with diabetes' ); // Do some other stuff } test('throws on pineapples', () => { // Test that the error message contains "diabetes" somewhere: these are equivalent expect(() => getFruitStock('pineapples')).toThrowError(/diabetes/); expect(() => getFruitStock('pineapples')).toThrowError('diabetes'); // Test the exact error message expect(() => getFruitStock('pineapples')).toThrowError( /^Pineapples are not good for people with diabetes$/ ); });TIP
Pro testování asynchronních funkcí použijte v kombinaci s rejects.
jsfunction getAsyncFruitStock() { return Promise.reject(new Error('empty')); } test('throws on pineapples', async () => { await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty'); });
toMatchSnapshot
Typ:
<T>(shape?: Partial<T> | string, message?: string) => voidZajišťuje, že hodnota odpovídá nejnovějšímu snímku (snapshot).
Můžete zadat volitelný řetězcový argument
hint, který se připojí k názvu testu. Ačkoli Vitest vždy připojí číslo na konec názvu snímku, krátké popisné nápovědy mohou být užitečnější než čísla pro rozlišení více snímků v jednom blokuitnebotest. Vitest třídí snímky podle názvu v odpovídajícím souboru.snap.TIP
Pokud snímek nesouhlasí a způsobí selhání testu, a tento nesoulad je očekávaný, můžete stiskem klávesy
usnímek jednorázově aktualizovat. Nebo můžete předat možnosti CLI-unebo--update, aby Vitest vždy aktualizoval testy.tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchSnapshot(); });Můžete také zadat tvar objektu, pokud testujete pouze tvar objektu a nepotřebujete, aby byl 100% kompatibilní:
tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchSnapshot({ foo: expect.any(Set) }); });
toMatchInlineSnapshot
Typ:
<T>(shape?: Partial<T> | string, snapshot?: string, message?: string) => voidZajišťuje, že hodnota odpovídá nejnovějšímu inline snímku (snapshot).
Vitest přidá a aktualizuje argument řetězce
inlineSnapshotdo porovnávače v testovacím souboru (místo externího souboru.snap).tsimport { expect, test } from 'vitest'; test('matches inline snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; // Vitest will update following content when updating the snapshot expect(data).toMatchInlineSnapshot(` { "foo": Set { "bar", "snapshot", }, } `); });Můžete také zadat tvar objektu, pokud testujete pouze tvar objektu a nepotřebujete, aby byl 100% kompatibilní:
tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchInlineSnapshot( { foo: expect.any(Set) }, ` { "foo": Any<Set>, } ` ); });
toMatchFileSnapshot
Typ:
<T>(filepath: string, message?: string) => Promise<void>Verze: Od Vitest 0.30.0
Porovná nebo aktualizuje snímek (snapshot) s obsahem souboru explicitně určeného cestou (místo souboru
.snap).tsimport { expect, it } from 'vitest'; it('render basic', async () => { const result = renderHTML(h('div', { class: 'foo' })); await expect(result).toMatchFileSnapshot('./test/basic.output.html'); });Všimněte si, že protože operace se systémem souborů je asynchronní, musíte použít
awaitstoMatchFileSnapshot().
toThrowErrorMatchingSnapshot
Typ:
(message?: string) => voidStejné jako
toMatchSnapshot, ale očekává stejnou hodnotu jakotoThrowError.Pokud funkce vyvolá
Error, snímek (snapshot) bude chybová zpráva. Jinak bude snímek hodnota vyvolaná funkcí.
toThrowErrorMatchingInlineSnapshot
Typ:
(snapshot?: string, message?: string) => voidStejné jako
toMatchInlineSnapshot, ale očekává stejnou hodnotu jakotoThrowError.Pokud funkce vyvolá
Error, snímek (snapshot) bude chybová zpráva. Jinak bude snímek hodnota vyvolaná funkcí.
toHaveBeenCalled
Typ:
() => Awaitable<void>Toto tvrzení je užitečné pro testování, zda byla funkce skutečně volána. Vyžaduje předání špehovací funkce (spy function) do
expect.tsimport { expect, test, vi } from 'vitest'; const market = { buy(subject: string, amount: number) { // ... }, }; test('spy function', () => { const buySpy = vi.spyOn(market, 'buy'); expect(buySpy).not.toHaveBeenCalled(); market.buy('apples', 10); expect(buySpy).toHaveBeenCalled(); });
toHaveBeenCalledTimes
- Typ:
(amount: number) => Awaitable<void>
Toto tvrzení kontroluje, zda byla funkce volána určitý počet krát. Vyžaduje předání špehovací funkce (spy function) do expect.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('spy function called two times', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).toHaveBeenCalledTimes(2);
});toHaveBeenCalledWith
- Typ:
(...args: any[]) => Awaitable<void>
Toto tvrzení kontroluje, zda byla funkce volána alespoň jednou s určitými parametry. Vyžaduje předání špehovací funkce (spy function) do expect.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('spy function', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).toHaveBeenCalledWith('apples', 10);
expect(buySpy).toHaveBeenCalledWith('apples', 20);
});toHaveBeenLastCalledWith
- Typ:
(...args: any[]) => Awaitable<void>
Toto tvrzení kontroluje, zda byla funkce volána s určitými parametry při posledním vyvolání. Vyžaduje předání špehovací funkce (spy function) do expect.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('spy function', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).not.toHaveBeenLastCalledWith('apples', 10);
expect(buySpy).toHaveBeenLastCalledWith('apples', 20);
});toHaveBeenNthCalledWith
- Typ:
(time: number, ...args: any[]) => Awaitable<void>
Toto tvrzení kontroluje, zda byla funkce volána s určitými parametry v určitém pořadí volání. Počet začíná na 1. Takže pro kontrolu druhého volání byste napsali .toHaveBeenNthCalledWith(2, ...)
Vyžaduje předání špehovací funkce (spy function) do expect.
import { expect, test, vi } from 'vitest';
const market = {
buy(subject: string, amount: number) {
// ...
},
};
test('first call of spy function called with right params', () => {
const buySpy = vi.spyOn(market, 'buy');
market.buy('apples', 10);
market.buy('apples', 20);
expect(buySpy).toHaveBeenNthCalledWith(1, 'apples', 10);
});toHaveReturned
- Typ:
() => Awaitable<void>
Toto tvrzení kontroluje, zda funkce úspěšně vrátila hodnotu alespoň jednou (tj. že nevyvolala chybu). Vyžaduje předání špehovací funkce (spy function) do expect.
import { expect, test, vi } from 'vitest';
function getApplesPrice(amount: number) {
const PRICE = 10;
return amount * PRICE;
}
test('spy function returned a value', () => {
const getPriceSpy = vi.fn(getApplesPrice);
const price = getPriceSpy(10);
expect(price).toBe(100);
expect(getPriceSpy).toHaveReturned();
});toHaveReturnedTimes
- Typ:
(amount: number) => Awaitable<void>
Toto tvrzení kontroluje, zda funkce úspěšně vrátila hodnotu přesný počet krát (tj. že nevyvolala chybu). Vyžaduje předání špehovací funkce (spy function) do expect.
import { expect, test, vi } from 'vitest';
test('spy function returns a value two times', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveReturnedTimes(2);
});toHaveReturnedWith
- Typ:
(returnValue: any) => Awaitable<void>
Tuto aserci použijte ke kontrole, zda funkce alespoň jednou vrátila zadanou hodnotu. Vyžaduje, aby byla do expect předána sledovací funkce (mock function).
import { expect, test, vi } from 'vitest';
test('sledovací funkce vrací produkt', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
expect(sell).toHaveReturnedWith({ product: 'apples' });
});toHaveLastReturnedWith
- Typ:
(returnValue: any) => Awaitable<void>
Tuto aserci použijte ke kontrole, zda funkce při svém posledním volání vrátila zadanou hodnotu. Vyžaduje, aby byla do expect předána sledovací funkce (mock function).
import { expect, test, vi } from 'vitest';
test('sledovací funkce při posledním volání vrací banány', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});toHaveNthReturnedWith
- Typ:
(time: number, returnValue: any) => Awaitable<void>
Tuto aserci použijte ke kontrole, zda funkce při konkrétním volání (určeném indexem) vrátila zadanou hodnotu. Vyžaduje, aby byla do expect předána sledovací funkce (mock function).
import { expect, test, vi } from 'vitest';
test('sledovací funkce při druhém volání vrací banány', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' });
});toSatisfy
- Typ:
(predicate: (value: any) => boolean) => Awaitable<void>
Tato aserce ověřuje, zda hodnota splňuje zadaný predikát (podmínku).
describe('toSatisfy()', () => {
const isOdd = (value: number) => value % 2 !== 0;
it('projde s hodnotou 1', () => {
expect(1).toSatisfy(isOdd);
});
it('projde při negaci', () => {
expect(2).not.toSatisfy(isOdd);
});
});resolves
Typ:
Promisify<Assertions>resolveszjednodušuje psaní asercí pro asynchronní kód. Použijte jej k získání hodnoty z vyřešené promise a ověření této hodnoty pomocí standardních asercí. Pokud promise bude zamítnuta (rejected), aserce selže.Vrací stejný objekt
Assertions, ale všechny matchery nyní vracíPromise, takže je nutné jeawaitovat. Funguje také s asercemichai.Například, pokud máte funkci, která provádí volání API a vrací data, můžete použít tento kód k ověření její návratové hodnoty:
tsimport { expect, test } from 'vitest'; async function buyApples() { return fetch('/buy/apples').then(r => r.json()); } test('buyApples vrací nové ID skladu', async () => { // toEqual nyní vrací promise, takže ji MUSÍTE awaitovat await expect(buyApples()).resolves.toEqual({ id: 1 }); // jest API await expect(buyApples()).resolves.to.equal({ id: 1 }); // chai API });WARNING
Pokud aserce není awaitována, dojde k falešně pozitivnímu testu, který projde pokaždé. Abyste se ujistili, že jsou aserce skutečně volány, můžete použít
expect.assertions(number).
rejects
Typ:
Promisify<Assertions>rejectszjednodušuje psaní asercí pro asynchronní kód. Použijte jej k získání důvodu zamítnutí (rejection) promise a ověření této hodnoty pomocí standardních asercí. Pokud promise bude vyřešena (resolved) úspěšně, aserce selže.Vrací stejný objekt
Assertions, ale všechny matchery nyní vracíPromise, takže je nutné jeawaitovat. Funguje také s asercemichai.Například, pokud máte funkci, která selže, můžete použít tento kód k ověření důvodu selhání:
tsimport { expect, test } from 'vitest'; async function buyApples(id) { if (!id) throw new Error('no id'); } test('buyApples vyvolá chybu, pokud není zadáno ID', async () => { // toThrow nyní vrací promise, takže ji MUSÍTE awaitovat await expect(buyApples()).rejects.toThrow('no id'); });WARNING
Pokud aserce není awaitována, dojde k falešně pozitivnímu testu, který projde pokaždé. Abyste se ujistili, že byly aserce skutečně volány, můžete použít
expect.assertions(number).
expect.assertions
Typ:
(count: number) => voidOvěří, zda byl během testu volán zadaný počet asercí. To je užitečné například pro kontrolu, zda byl volán asynchronní kód. Tato kontrola se provádí po dokončení testu (úspěšném či neúspěšném).
Například, pokud máme funkci, která asynchronně volá dva matchery, můžeme ověřit, že byly skutečně volány.
tsimport { expect, test } from 'vitest'; async function doAsync(...cbs) { await Promise.all(cbs.map((cb, index) => cb({ index }))); } test('všechny aserce jsou volány', async () => { expect.assertions(2); function callback1(data) { expect(data).toBeTruthy(); } function callback2(data) { expect(data).toBeTruthy(); } await doAsync(callback1, callback2); });WARNING
Při použití
assertionss asynchronními souběžnými testy musí být použitexpectz lokálního Test Context, aby byl zajištěn správný test.
expect.hasAssertions
Typ:
() => voidOvěří, zda byla během testu volána alespoň jedna aserce. To je užitečné například pro kontrolu, zda byl volán asynchronní kód. Tato kontrola se provádí po dokončení testu (úspěšném či neúspěšném).
Například, pokud máte kód, který volá callback, můžeme provést aserci uvnitř callbacku, ale test vždy projde, pokud nezkontrolujeme, zda byla aserce volána.
tsimport { expect, test } from 'vitest'; import { db } from './db.js'; const cbs = []; function onSelect(cb) { cbs.push(cb); } // po výběru z databáze voláme všechny callbacky function select(id) { return db.select({ id }).then(data => { return Promise.all(cbs.map(cb => cb(data))); }); } test('callback byl volán', async () => { expect.hasAssertions(); onSelect(data => { // měl by být volán při select expect(data).toBeTruthy(); }); // pokud chybí await, test selže // bez expect.hasAssertions() test projde await select(3); });
expect.unreachable
Typ:
(message?: string) => neverTato metoda slouží k ověření, že daný řádek kódu by neměl být nikdy vykonán. Pokud je vykonán, test selže.
Například, pokud chceme otestovat, že funkce
build()vyvolá výjimku, protože obdržela adresáře, které neobsahují složkusrc, a zároveň chceme zpracovat každou chybu individuálně, můžeme postupovat takto:tsimport { expect, test } from 'vitest'; async function build(dir) { if (dir.includes('no-src')) throw new Error(`${dir}/src does not exist`); } const errorDirs = [ 'no-src-folder', // ... ]; test.each(errorDirs)('build neprojde pro "%s"', async dir => { try { await build(dir); expect.unreachable('Build by neměl projít'); } catch (err: any) { expect(err).toBeInstanceOf(Error); expect(err.stack).toContain('build'); switch (dir) { case 'no-src-folder': expect(err.message).toBe(`${dir}/src does not exist`); break; default: // pro vyčerpání všech chybových testů expect.unreachable('Všechny testy chyb musí být ošetřeny'); break; } } });
expect.anything
Typ:
() => anyTento asymetrický matcher, pokud je použit s operátorem rovnosti, vždy vrátí
true. Je užitečný, pokud chcete ověřit pouze existenci dané vlastnosti.tsimport { expect, test } from 'vitest'; test('objekt má klíč "apples"', () => { expect({ apples: 22 }).toEqual({ apples: expect.anything() }); });
expect.any
Typ:
(constructor: unknown) => anyTento asymetrický matcher, pokud je použit s operátorem rovnosti, vrátí
truepouze v případě, že je hodnota instancí zadaného konstruktoru (typu). Je užitečný, pokud máte hodnotu, která je generována dynamicky, a chcete ověřit pouze její typ.tsimport { expect, test } from 'vitest'; import { generateId } from './generators.js'; test('"id" je číslo', () => { expect({ id: generateId() }).toEqual({ id: expect.any(Number) }); });
expect.arrayContaining
Typ:
<T>(expected: T[]) => anyPokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
truev případě, že je hodnota pole a obsahuje všechny zadané prvky.tsimport { expect, test } from 'vitest'; test('košík obsahuje fuji', () => { const basket = { varieties: ['Empire', 'Fuji', 'Gala'], count: 3, }; expect(basket).toEqual({ count: 3, varieties: expect.arrayContaining(['Fuji']), }); });TIP
Můžete použít
expect.nots tímto matcherem k negaci očekávané hodnoty.
expect.objectContaining
Typ:
(expected: any) => anyPokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
truev případě, že hodnota je objekt a má podobnou strukturu (obsahuje alespoň zadané vlastnosti).tsimport { expect, test } from 'vitest'; test('košík má jablka empire', () => { const basket = { varieties: [ { name: 'Empire', count: 1, }, ], }; expect(basket).toEqual({ varieties: [expect.objectContaining({ name: 'Empire' })], }); });TIP
Můžete použít
expect.nots tímto matcherem k negaci očekávané hodnoty.
expect.stringContaining
Typ:
(expected: any) => anyPokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
truev případě, že hodnota je řetězec a obsahuje zadaný podřetězec.tsimport { expect, test } from 'vitest'; test('odrůda má v názvu "Emp"', () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringContaining('Emp'), count: 1, }); });TIP
Můžete použít
expect.nots tímto matcherem k negaci očekávané hodnoty.
expect.stringMatching
Typ:
(expected: any) => anyPokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
truev případě, že hodnota je řetězec a obsahuje zadaný podřetězec, nebo pokud řetězec odpovídá zadanému regulárnímu výrazu.tsimport { expect, test } from 'vitest'; test('odrůda končí na "re"', () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringMatching(/re$/), count: 1, }); });TIP
Můžete použít
expect.nots tímto matcherem k negaci očekávané hodnoty.
expect.addSnapshotSerializer
Typ:
(plugin: PrettyFormatPlugin) => voidTato metoda přidává vlastní serializátory, které se používají při vytváření snapshotů. Toto je pokročilá vlastnost. Pro více informací si přečtěte průvodce vlastními serializátory.
Pokud používáte vlastní serializátory, doporučuje se volat tuto metodu uvnitř
setupFiles. To ovlivní každý snapshot.TIP
Pokud jste dříve používali Vue CLI s Jest, možná budete chtít nainstalovat jest-serializer-vue. V opačném případě budou vaše snapshoty zabaleny do řetězce, což povede k escapování znaků
"."
expect.extend
Typ:
(matchers: MatchersObject) => voidMůžete rozšířit sadu výchozích matcherů o vlastní. Tato funkce slouží k rozšíření objektu matcherů o vlastní implementace.
Při definování matcherů tímto způsobem se automaticky vytvoří i odpovídající asymetrické matchery, které lze použít například jako
expect.stringContaining.tsimport { expect, test } from 'vitest'; test('vlastní matchery', () => { expect.extend({ toBeFoo: (received, expected) => { if (received !== 'foo') { return { message: () => `očekává se, že ${received} bude foo`, pass: false, }; } }, }); expect('foo').toBeFoo(); expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() }); });TIP
Pokud chcete, aby byly vaše matchery dostupné v každém testu, doporučuje se volat tuto metodu uvnitř
setupFiles.Tato funkce je kompatibilní s funkcí
expect.extendz Jestu, takže jakákoli knihovna, která ji používá k vytváření vlastních matcherů, bude bez problémů fungovat i s Vitest.Pokud používáte TypeScript, můžete od verze Vitest 0.31.0 rozšířit výchozí rozhraní
Assertionv souboru s ambientní deklarací (např.vitest.d.ts) pomocí následujícího kódu:tsinterface CustomMatchers<R = unknown> { toBeFoo(): R; } declare module 'vitest' { interface Assertion<T = any> extends CustomMatchers<T> {} interface AsymmetricMatchersContaining extends CustomMatchers {} }WARNING
Ujistěte se, že jste zahrnuli soubor s ambientní deklarací do konfigurace
tsconfig.json.TIP
Pokud se chcete dozvědět více, podívejte se na průvodce rozšířením matcherů.