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 API
Z 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 API
toBe
Typ:
(value: any) => Awaitable<void>
toBe
slouží 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í
toBe
s čísly s plovoucí desetinnou čárkou. Protože je JavaScript zaokrouhluje,0.1 + 0.2
není 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
toBeCloseTo
k porovnání čísel s plovoucí desetinnou čárkou. Volitelný argumentnumDigits
urč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>
toBeDefined
ověř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
toBeDefined
jetoBeUndefined
, 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>
toBeTruthy
ověř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.getInfo
bude 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
,undefined
aNaN
.
toBeFalsy
Typ:
() => Awaitable<void>
toBeFalsy
ověř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.stockFailed
bude 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
,undefined
aNaN
.
toBeNull
Typ:
() => Awaitable<void>
toBeNull
jednoduš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>
toBeNaN
jednoduš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>
toBeTypeOf
ověř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>
toBeInstanceOf
ověř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>
toBeGreaterThan
ověř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>
toBeGreaterThanOrEqual
ověř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>
toBeLessThan
ověř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>
toBeLessThanOrEqual
ověř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>
toEqual
ověř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 mezitoEqual
atoBe
můž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>
toStrictEqual
ověř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
undefined
jsou 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
a
ab
se nebude rovnat literálovému objektu s atributya
ab
.
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>
toContain
ověřuje, zda je skutečná hodnota obsažena v poli.toContain
také 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>
toContainEqual
ověřuje, zda je v poli obsažena položka se specifickou strukturou a hodnotami. Funguje jakotoEqual
uvnitř 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>
toHaveLength
ověřuje, zda má objekt vlastnost.length
a 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>
toHaveProperty
ověř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>
toMatch
ověř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>
toMatchObject
ověř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:
toThrow
toThrowError
ověř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) => void
Zajišť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 blokuit
nebotest
. 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
u
snímek jednorázově aktualizovat. Nebo můžete předat možnosti CLI-u
nebo--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) => void
Zajišťuje, že hodnota odpovídá nejnovějšímu inline snímku (snapshot).
Vitest přidá a aktualizuje argument řetězce
inlineSnapshot
do 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
await
stoMatchFileSnapshot()
.
toThrowErrorMatchingSnapshot
Typ:
(message?: string) => void
Stejné 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) => void
Stejné 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>
resolves
zjednoduš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é jeawait
ovat. 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>
rejects
zjednoduš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é jeawait
ovat. 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) => void
Ověří, 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í
assertions
s asynchronními souběžnými testy musí být použitexpect
z lokálního Test Context, aby byl zajištěn správný test.
expect.hasAssertions
Typ:
() => void
Ověří, 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) => never
Tato 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:
() => any
Tento 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) => any
Tento asymetrický matcher, pokud je použit s operátorem rovnosti, vrátí
true
pouze 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[]) => any
Pokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
true
v 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.not
s tímto matcherem k negaci očekávané hodnoty.
expect.objectContaining
Typ:
(expected: any) => any
Pokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
true
v 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.not
s tímto matcherem k negaci očekávané hodnoty.
expect.stringContaining
Typ:
(expected: any) => any
Pokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
true
v 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.not
s tímto matcherem k negaci očekávané hodnoty.
expect.stringMatching
Typ:
(expected: any) => any
Pokud je tento asymetrický matcher použit s operátorem rovnosti, vrátí
true
v 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.not
s tímto matcherem k negaci očekávané hodnoty.
expect.addSnapshotSerializer
Typ:
(plugin: PrettyFormatPlugin) => void
Tato 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) => void
Můž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.extend
z 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í
Assertion
v 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ů.