expect
I seguenti tipi sono utilizzati nelle definizioni di tipo sottostanti:
type Awaitable<T> = T | PromiseLike<T>;expect viene utilizzato per creare asserzioni. In questo contesto, le asserzioni sono funzioni che vengono invocate per verificare un'affermazione. Vitest fornisce asserzioni chai di default, e anche asserzioni compatibili con Jest basate su chai.
Ad esempio, questo codice asserisce che un valore input sia uguale a 2. In caso contrario, l'asserzione lancerà un errore e il test fallirà.
import { expect } from 'vitest';
const input = Math.sqrt(4);
expect(input).to.equal(2); // API chai
expect(input).toBe(2); // API jestQuesto esempio non utilizza la funzione test, quindi nella console verrà visualizzato un errore di Node.js invece dell'output di Vitest. Per saperne di più su test, consulta Test API Reference.
Inoltre, expect può essere usato staticamente per accedere alle funzioni dei matcher, descritte più avanti, e altro ancora.
WARNING
expect non influisce sui tipi di test, a meno che l'espressione non contenga un errore di tipo. Se si desidera utilizzare Vitest come verificatore di tipo, utilizzare expectTypeOf o assertType.
soft
- Tipo:
ExpectStatic & (actual: any) => Assertions
expect.soft funziona in modo simile a expect, ma, in caso di fallimento dell'asserzione, invece di terminare l'esecuzione del test, continua e segnala l'errore come un fallimento del test. Tutti gli errori riscontrati durante il test verranno visualizzati al termine del test.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // segnala il fallimento ma continua
expect.soft(1 + 2).toBe(4); // segnala il fallimento ma continua
});
// Alla fine del test, gli errori verranno visualizzati.Può essere usato anche con expect. Se l'asserzione expect fallisce, il test viene terminato e tutti gli errori vengono visualizzati.
import { expect, test } from 'vitest';
test('expect.soft test', () => {
expect.soft(1 + 1).toBe(3); // segnala il fallimento ma continua
expect(1 + 2).toBe(3); // fallisce e interrompe il test, tutti gli errori precedenti verranno visualizzati
expect.soft(1 + 2).toBe(4); // non viene eseguito
});WARNING
expect.soft può essere usato solo all'interno della funzione test.
not
L'uso di not nega l'asserzione. Ad esempio, questo codice asserisce che un valore input non sia uguale a 2. Se lo è, l'asserzione lancerà un errore e il test fallirà.
import { expect, test } from 'vitest';
const input = Math.sqrt(16);
expect(input).not.to.equal(2); // API chai
expect(input).not.toBe(2); // API jesttoBe
Tipo:
(value: any) => Awaitable<void>toBepuò essere usato per asserire se i tipi primitivi sono uguali o se gli oggetti condividono lo stesso riferimento. È equivalente a chiamareexpect(Object.is(3, 3)).toBe(true). Se gli oggetti non sono identici, ma si vuole verificare se le loro strutture sono uguali, si può usaretoEqual.Ad esempio, il codice qui sotto controlla se il commerciante ha 13 mele.
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; // stesso riferimento expect(stock).toBe(refStock); });È consigliabile non usare
toBecon numeri in virgola mobile. Poiché JavaScript li approssima,0.1 + 0.2non è esattamente0.3. Per asserire in modo affidabile numeri in virgola mobile, usa l'asserzionetoBeCloseTo.
toBeCloseTo
Tipo:
(value: number, numDigits?: number) => Awaitable<void>Usa
toBeCloseToper confrontare numeri in virgola mobile. L'argomento opzionalenumDigitslimita il numero di cifre da controllare dopo la virgola. Ad esempio: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 è 0.30000000000000004 }); test('decimals are rounded to 5 after the point', () => { // 0.2 + 0.1 è 0.30000 | "000000000004" rimosso expect(0.2 + 0.1).toBeCloseTo(0.3, 5); // niente da 0.30000000000000004 viene rimosso expect(0.2 + 0.1).not.toBeCloseTo(0.3, 50); });
toBeDefined
Tipo:
() => Awaitable<void>toBeDefinedasserisce che il valore non è uguale aundefined. È utile per verificare se una funzione ha restituito un valore.tsimport { expect, test } from 'vitest'; function getApples() { return 3; } test('function returned something', () => { expect(getApples()).toBeDefined(); });
toBeUndefined
Tipo:
() => Awaitable<void>Al contrario di
toBeDefined,toBeUndefinedverifica che il valore sia uguale aundefined. Un caso d'uso utile è verificare se una funzione non ha restituito alcun valore.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
Tipo:
() => Awaitable<void>toBeTruthyasserisce che il valore è vero quando convertito in booleano. Utile se non si è interessati al valore specifico, ma si vuole solo sapere se può essere convertito intrue.Ad esempio, avendo questo codice non si è interessati al valore di ritorno di
stocks.getInfo- potrebbe essere un oggetto complesso, una stringa o qualsiasi altra cosa. Il codice funzionerà comunque.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (stocks.getInfo('Bill')) stocks.sell('apples', 'Bill');Quindi, se vuoi testare che
stocks.getInfosarà truthy, potresti scrivere: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(); });In JavaScript tutti i valori sono considerati truthy, eccetto
false,0,'',null,undefinedeNaN.
toBeFalsy
Tipo:
() => Awaitable<void>toBeFalsyasserisce che il valore è falso quando convertito in booleano. Utile se non si è interessati al valore specifico, ma si vuole solo sapere se può essere convertito infalse.Ad esempio, avendo questo codice non si è interessati al valore di ritorno di
stocks.stockFailed- potrebbe restituire qualsiasi valore falsy, ma il codice funzionerà comunque.tsimport { Stocks } from './stocks.js'; const stocks = new Stocks(); stocks.sync('Bill'); if (!stocks.stockFailed('Bill')) stocks.sell('apples', 'Bill');Quindi, se vuoi testare che
stocks.stockFailedsarà falsy, potresti scrivere: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(); });In JavaScript tutti i valori sono considerati truthy, eccetto
false,0,'',null,undefinedeNaN.
toBeNull
Tipo:
() => Awaitable<void>toBeNullverifica semplicemente se un valore ènull. Alias per.toBe(null).tsimport { expect, test } from 'vitest'; function apples() { return null; } test("we don't have apples", () => { expect(apples()).toBeNull(); });
toBeNaN
Tipo:
() => Awaitable<void>toBeNaNverifica semplicemente se un valore èNaN. Alias per.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
Tipo:
(c: 'bigint' | 'boolean' | 'function' | 'number' | 'object' | 'string' | 'symbol' | 'undefined') => Awaitable<void>toBeTypeOfverifica se il tipo di un valore corrisponde al tipo specificato.tsimport { expect, test } from 'vitest'; const actual = 'stock'; test('stock is type of string', () => { expect(actual).toBeTypeOf('string'); });
toBeInstanceOf
Tipo:
(c: any) => Awaitable<void>toBeInstanceOfverifica se un valore è un'istanza della classe specificata.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
Tipo:
(n: number | bigint) => Awaitable<void>toBeGreaterThanverifica se un valore è maggiore di un altro. Valori uguali causeranno il fallimento del test.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have more then 10 apples', () => { expect(getApples()).toBeGreaterThan(10); });
toBeGreaterThanOrEqual
Tipo:
(n: number | bigint) => Awaitable<void>toBeGreaterThanOrEqualverifica se un valore è maggiore o uguale a un altro.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have 11 apples or more', () => { expect(getApples()).toBeGreaterThanOrEqual(11); });
toBeLessThan
Tipo:
(n: number | bigint) => Awaitable<void>toBeLessThanverifica se un valore è minore di un altro. Valori uguali causeranno il fallimento del test.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have less then 20 apples', () => { expect(getApples()).toBeLessThan(20); });
toBeLessThanOrEqual
Tipo:
(n: number | bigint) => Awaitable<void>toBeLessThanOrEqualverifica se un valore è minore o uguale a un altro.tsimport { expect, test } from 'vitest'; import { getApples } from './stocks.js'; test('have 11 apples or less', () => { expect(getApples()).toBeLessThanOrEqual(11); });
toEqual
Tipo:
(received: any) => Awaitable<void>toEqualverifica se un valore è uguale a un altro, o se ha la stessa struttura nel caso di oggetti (confronto ricorsivo). Puoi vedere la differenza tratoEqualetoBein questo esempio: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
Una deep equality non verrà eseguita per gli oggetti
Error. Per testare se qualcosa è stato lanciato, usa l'asserzionetoThrowError.
toStrictEqual
Tipo:
(received: any) => Awaitable<void>toStrictEqualverifica se un valore è uguale a un altro, o se ha la stessa struttura e tipo nel caso di oggetti (confronto ricorsivo).Differenze da
.toEqual:- Le chiavi con proprietà
undefinedvengono controllate. es.{a: undefined, b: 2}non corrisponde a{b: 2}quando si usa.toStrictEqual. - Viene verificata la presenza di elementi vuoti nell'array. es.
[, 1]non corrisponde a[undefined, 1]quando si usa.toStrictEqual. - I tipi di oggetto vengono controllati per essere uguali. es. Un'istanza di classe con campi
aebnon sarà uguale a un oggetto letterale con campiaeb.
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' }); });- Le chiavi con proprietà
toContain
Tipo:
(received: string) => Awaitable<void>toContainverifica se un array contiene un determinato valore.toContainpuò anche verificare se una stringa è contenuta in un'altra stringa.tsimport { expect, test } from 'vitest'; import { getAllFruits } from './stocks.js'; test('the fruit list contains orange', () => { expect(getAllFruits()).toContain('orange'); });
toContainEqual
Tipo:
(received: any) => Awaitable<void>toContainEqualverifica se un array contiene un elemento con una specifica struttura e valori. Funziona cometoEqualall'interno per ogni elemento.tsimport { expect, test } from 'vitest'; import { getFruitStock } from './stocks.js'; test('apple available', () => { expect(getFruitStock()).toContainEqual({ fruit: 'apple', count: 5 }); });
toHaveLength
Tipo:
(received: number) => Awaitable<void>toHaveLengthverifica se un oggetto ha una proprietà.lengthcon un determinato valore numerico.tsimport { expect, test } from 'vitest'; test('toHaveLength', () => { expect('abc').toHaveLength(3); expect([1, 2, 3]).toHaveLength(3); expect('').not.toHaveLength(3); // non ha .length di 3 expect({ length: 3 }).toHaveLength(3); });
toHaveProperty
Tipo:
(key: any, received?: any) => Awaitable<void>toHavePropertyverifica se un oggetto possiede una proprietà con la chiave specificata (key).È possibile fornire un argomento valore opzionale per eseguire un confronto di uguaglianza profonda (deep equality), simile al matcher
toEqual, con il valore della proprietà.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'); // Verifica che la proprietà esista expect(invoice).toHaveProperty('total_amount', 5000); // Verifica che la chiave esista e che il valore corrisponda expect(invoice).not.toHaveProperty('account'); // Verifica che la proprietà non esista // Riferimento a proprietà annidate usando la notazione a punti expect(invoice).toHaveProperty('customer.first_name'); expect(invoice).toHaveProperty('customer.last_name', 'Doe'); expect(invoice).not.toHaveProperty('customer.location', 'India'); // Riferimento a proprietà annidate usando un array contenente la chiave expect(invoice).toHaveProperty('items[0].type', 'apples'); expect(invoice).toHaveProperty('items.0.type', 'apples'); // Anche la notazione a punti funziona // Riferimento a proprietà annidate usando un array contenente il keyPath expect(invoice).toHaveProperty(['items', 0, 'type'], 'apples'); expect(invoice).toHaveProperty(['items', '0', 'type'], 'apples'); // Funziona anche la notazione stringa // Includi la chiave in un array per evitare che venga interpretata come riferimento a proprietà annidata expect(invoice).toHaveProperty(['P.O'], '12345'); });
toMatch
Tipo:
(received: string | regexp) => Awaitable<void>toMatchverifica se una stringa corrisponde a un'espressione regolare.tsimport { expect, test } from 'vitest'; test('top fruits', () => { expect('top fruits include apple, orange and grape').toMatch(/apple/); expect('applefruits').toMatch('fruit'); // toMatch accetta anche stringhe });
TIP
Se il valore nel messaggio di errore viene troncato, è possibile aumentare [chaiConfig.truncateThreshold](../config/#chaiconfig-truncatethreshold) nel file di configurazione.
toMatchObject
Tipo:
(received: object | array) => Awaitable<void>toMatchObjectverifica se un oggetto corrisponde a un sottoinsieme delle proprietà di un altro oggetto.È possibile fornire anche un array di oggetti. Questo è utile per verificare che due array abbiano lo stesso numero di elementi, a differenza di
arrayContainingche permette elementi aggiuntivi nell'array ricevuto.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', () => { // Verifica che un array di oggetti corrisponda expect([{ foo: 'bar' }, { baz: 1 }]).toMatchObject([ { foo: 'bar' }, { baz: 1 }, ]); });
toThrowError
Tipo:
(received: any) => Awaitable<void>Alias:
toThrowtoThrowErrorverifica se una funzione genera un errore quando viene invocata.È possibile fornire un argomento opzionale per verificare che venga generato un tipo di errore specifico:
- espressione regolare: il messaggio di errore deve corrispondere al pattern.
- stringa: il messaggio di errore deve includere la sottostringa.
TIP
È necessario racchiudere il codice in una funzione, altrimenti l'errore non verrà catturato e il test fallirà.
Ad esempio, per verificare che
getFruitStock('pineapples')generi un'eccezione, si può scrivere:tsimport { expect, test } from 'vitest'; function getFruitStock(type) { if (type === 'pineapples') throw new DiabetesError( 'Pineapples are not good for people with diabetes' ); // Esegui altre operazioni } test('throws on pineapples', () => { // Verifica che il messaggio di errore contenga "diabetes": questi sono equivalenti expect(() => getFruitStock('pineapples')).toThrowError(/diabetes/); expect(() => getFruitStock('pineapples')).toThrowError('diabetes'); // Verifica l'esatto messaggio di errore expect(() => getFruitStock('pineapples')).toThrowError( /^Pineapples are not good for people with diabetes$/ ); });TIP
Per testare funzioni asincrone, utilizzare in combinazione con rejects.
jsfunction getAsyncFruitStock() { return Promise.reject(new Error('empty')); } test('throws on pineapples', async () => { await expect(() => getAsyncFruitStock()).rejects.toThrowError('empty'); });
toMatchSnapshot
Tipo:
<T>(shape?: Partial<T> | string, message?: string) => voidQuesto metodo verifica che un valore corrisponda all'ultimo snapshot salvato.
È possibile fornire una stringa
hintopzionale che viene aggiunta al nome del test. Sebbene Vitest aggiunga sempre un numero alla fine del nome di uno snapshot, brevi suggerimenti descrittivi possono essere più utili dei numeri per differenziare più snapshot all'interno di un singolo bloccoito test. Vitest ordina gli snapshot per nome nel file.snapassociato.TIP
Quando lo snapshot non corrisponde e causa il fallimento del test, se la mancata corrispondenza è prevista, è possibile premere
uper aggiornare lo snapshot. In alternativa, è possibile passare le opzioni CLI-uo--updateper fare in modo che Vitest aggiorni sempre gli snapshot.tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchSnapshot(); });È anche possibile fornire una "forma" di un oggetto, se si sta testando solo una parte dell'oggetto e non è necessario che sia compatibile al 100%:
tsimport { expect, test } from 'vitest'; test('matches snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; expect(data).toMatchSnapshot({ foo: expect.any(Set) }); });
toMatchInlineSnapshot
Tipo:
<T>(shape?: Partial<T> | string, snapshot?: string, message?: string) => voidQuesto metodo verifica che un valore corrisponda all'ultimo snapshot salvato.
Vitest aggiunge e aggiorna l'argomento
inlineSnapshot(di tipo stringa) direttamente nel file di test, all'interno del matcher (invece di utilizzare un file.snapesterno).tsimport { expect, test } from 'vitest'; test('matches inline snapshot', () => { const data = { foo: new Set(['bar', 'snapshot']) }; // Vitest aggiornerà il seguente contenuto quando si aggiorna lo snapshot expect(data).toMatchInlineSnapshot(` { "foo": Set { "bar", "snapshot", }, } `); });È anche possibile fornire una "forma" di un oggetto, se si sta testando solo una parte dell'oggetto e non è necessario che sia compatibile al 100%:
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
Tipo:
<T>(filepath: string, message?: string) => Promise<void>Versione: Da Vitest 0.30.0
Confronta o aggiorna lo snapshot con il contenuto di un file specificato esplicitamente (invece del file
.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'); });Poiché l'operazione di accesso al file system è asincrona, è necessario utilizzare
awaitcontoMatchFileSnapshot().
toThrowErrorMatchingSnapshot
Tipo:
(message?: string) => voidFunziona come
toMatchSnapshot, ma si aspetta lo stesso valore ditoThrowError.Se la funzione genera un
Error, lo snapshot sarà il messaggio di errore. Altrimenti, lo snapshot sarà il valore restituito dalla funzione.
toThrowErrorMatchingInlineSnapshot
Tipo:
(snapshot?: string, message?: string) => voidFunziona come
toMatchInlineSnapshot, ma si aspetta lo stesso valore ditoThrowError.Se la funzione genera un
Error, lo snapshot sarà il messaggio di errore. Altrimenti, lo snapshot sarà il valore restituito dalla funzione.
toHaveBeenCalled
Tipo:
() => Awaitable<void>Questa asserzione è utile per verificare se una funzione è stata chiamata. Richiede di passare una spy function a
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
- Tipo:
(amount: number) => Awaitable<void>
Questa asserzione verifica se una funzione è stata chiamata un numero specifico di volte. Richiede di passare una spy function a 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
- Tipo:
(...args: any[]) => Awaitable<void>
Questa asserzione verifica se una funzione è stata chiamata almeno una volta con specifici parametri. Richiede di passare una spy function a 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
- Tipo:
(...args: any[]) => Awaitable<void>
Questa asserzione verifica se una funzione è stata chiamata con specifici parametri durante la sua ultima invocazione. Richiede di passare una spy function a 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
- Tipo:
(time: number, ...args: any[]) => Awaitable<void>
Questa asserzione verifica se una funzione è stata chiamata con specifici parametri in una specifica invocazione. Il conteggio parte da 1. Quindi, per controllare la seconda invocazione, si scriverebbe .toHaveBeenNthCalledWith(2, ...).
Richiede di passare una spy function a 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
- Tipo:
() => Awaitable<void>
Questa asserzione verifica se una funzione ha restituito un valore con successo almeno una volta (ovvero, senza generare un errore). Richiede di passare una spy function a 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
- Tipo:
(amount: number) => Awaitable<void>
Questa asserzione verifica se una funzione ha restituito un valore con successo un numero specifico di volte (ovvero, senza generare un errore). Richiede di passare una spy function a 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
- Tipo:
(returnValue: any) => Awaitable<void>
Questa asserzione verifica se una funzione spia ha restituito un valore specifico almeno una volta. Richiede che una funzione spia sia passata a expect.
import { expect, test, vi } from 'vitest';
test('la funzione spia restituisce un prodotto', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
expect(sell).toHaveReturnedWith({ product: 'apples' });
});toHaveLastReturnedWith
- Tipo:
(returnValue: any) => Awaitable<void>
Questa asserzione verifica se una funzione spia ha restituito un valore specifico all'ultima invocazione. Richiede che una funzione spia sia passata a expect.
import { expect, test, vi } from 'vitest';
test("la funzione spia restituisce banane all'ultima chiamata", () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveLastReturnedWith({ product: 'bananas' });
});toHaveNthReturnedWith
- Tipo:
(time: number, returnValue: any) => Awaitable<void>
Questa asserzione verifica se una funzione spia ha restituito un valore specifico alla n-esima chiamata. Richiede che una funzione spia sia passata a expect.
import { expect, test, vi } from 'vitest';
test('la funzione spia restituisce banane alla seconda chiamata', () => {
const sell = vi.fn((product: string) => ({ product }));
sell('apples');
sell('bananas');
expect(sell).toHaveNthReturnedWith(2, { product: 'bananas' });
});toSatisfy
- Tipo:
(predicate: (value: any) => boolean) => Awaitable<void>
Questa asserzione verifica se un valore soddisfa una condizione definita da un predicato.
describe('toSatisfy()', () => {
const isOdd = (value: number) => value % 2 !== 0;
it('passa con 1', () => {
expect(1).toSatisfy(isOdd);
});
it('passa con negato', () => {
expect(2).not.toSatisfy(isOdd);
});
});resolves
Tipo:
Promisify<Assertions>resolvessemplifica l'asserzione di codice asincrono. Permette di estrarre il valore di risoluzione di una Promise e verificarlo con le asserzioni standard. Se la Promise viene rifiutata, l'asserzione fallisce.Restituisce lo stesso oggetto
Assertions, ma tutti i matcher ora restituisconoPromise, quindi è necessario utilizzareawait. Funziona anche con le asserzionichai.Ad esempio, per una funzione che effettua una chiamata API e restituisce dei dati, si può asserire il valore di ritorno in questo modo:
tsimport { expect, test } from 'vitest'; async function buyApples() { return fetch('/buy/apples').then(r => r.json()); } test('buyApples restituisce il nuovo ID stock', async () => { // toEqual ora restituisce una promise, quindi DEVI usare await await expect(buyApples()).resolves.toEqual({ id: 1 }); // API jest await expect(buyApples()).resolves.to.equal({ id: 1 }); // API chai });WARNING
Se l'asserzione non viene attesa con
await, si otterrà un test falso positivo che passerà sempre. Per assicurarsi che le asserzioni vengano effettivamente eseguite, si può utilizzareexpect.assertions(number).
rejects
Tipo:
Promisify<Assertions>rejectssemplifica l'asserzione di codice asincrono. Permette di estrarre il motivo del rifiuto di una Promise e verificarlo con le asserzioni standard. Se la Promise viene risolta con successo, l'asserzione fallisce.Restituisce lo stesso oggetto
Assertions, ma tutti i matcher ora restituisconoPromise, quindi è necessario utilizzareawait. Funziona anche con le asserzionichai.Ad esempio, per una funzione che genera un errore, si può asserire il motivo del rifiuto in questo modo:
tsimport { expect, test } from 'vitest'; async function buyApples(id) { if (!id) throw new Error('no id'); } test('buyApples genera un errore quando non viene fornito alcun ID', async () => { // toThrow ora restituisce una promise, quindi DEVI usare await await expect(buyApples()).rejects.toThrow('no id'); });WARNING
Se l'asserzione non viene attesa con
await, si otterrà un test falso positivo che passerà sempre. Per assicurarsi che le asserzioni vengano effettivamente eseguite, si può utilizzareexpect.assertions(number).
expect.assertions
Tipo:
(count: number) => voidVerifica che un certo numero di asserzioni sia stato eseguito durante un test, dopo che il test è stato completato (con successo o fallimento). Questo è utile per verificare se è stato eseguito codice asincrono.
Ad esempio, se una funzione chiama asincronamente due matcher, si può asserire che siano stati effettivamente chiamati.
tsimport { expect, test } from 'vitest'; async function doAsync(...cbs) { await Promise.all(cbs.map((cb, index) => cb({ index }))); } test('tutte le asserzioni vengono chiamate', async () => { expect.assertions(2); function callback1(data) { expect(data).toBeTruthy(); } function callback2(data) { expect(data).toBeTruthy(); } await doAsync(callback1, callback2); });WARNING
Quando si utilizzano
assertionscon test asincroni concorrenti, è necessario utilizzareexpectdal Contesto di test locale per garantire che venga rilevato il test corretto.
expect.hasAssertions
Tipo:
() => voidVerifica che sia stata eseguita almeno un'asserzione durante un test, dopo che il test è stato completato (con successo o fallimento). Questo è utile per verificare se è stato eseguito codice asincrono.
Ad esempio, se un codice chiama una callback, si può fare un'asserzione all'interno della callback, ma il test passerà sempre se non si verifica se è stata chiamata un'asserzione.
tsimport { expect, test } from 'vitest'; import { db } from './db.js'; const cbs = []; function onSelect(cb) { cbs.push(cb); } // dopo aver selezionato dal db, chiamiamo tutte le callback function select(id) { return db.select({ id }).then(data => { return Promise.all(cbs.map(cb => cb(data))); }); } test('la callback è stata chiamata', async () => { expect.hasAssertions(); onSelect(data => { // dovrebbe essere chiamato su select expect(data).toBeTruthy(); }); // se non atteso, il test fallirà // se non hai expect.hasAssertions(), il test passerà await select(3); });
expect.unreachable
Tipo:
(message?: string) => neverQuesto metodo viene utilizzato per indicare che una riga di codice non dovrebbe mai essere raggiunta. Se viene raggiunta, il test fallisce.
Ad esempio, per testare che
build()generi un'eccezione a causa della ricezione di directory senza una cartellasrce gestire anche ogni errore separatamente, si potrebbe fare questo: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 fallisce con "%s"', async dir => { try { await build(dir); expect.unreachable('Non avrebbe dovuto superare la build'); } 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: // per esaurire tutti i test di errore expect.unreachable('Tutti i casi di errore devono essere gestiti'); break; } } });
expect.anything
Tipo:
() => anyQuesto matcher asimmetrico, se utilizzato in un controllo di uguaglianza, restituirà sempre
true. È utile quando si vuole solo verificare che una proprietà esista.tsimport { expect, test } from 'vitest'; test("l'oggetto contiene la chiave 'apples'", () => { expect({ apples: 22 }).toEqual({ apples: expect.anything() }); });
expect.any
Tipo:
(constructor: unknown) => anyQuesto matcher asimmetrico, se utilizzato in un controllo di uguaglianza, restituirà
truesolo se il valore è un'istanza del costruttore specificato. È utile quando si ha un valore che viene generato dinamicamente e si vuole solo verificare che sia del tipo corretto.tsimport { expect, test } from 'vitest'; import { generateId } from './generators.js'; test('"id" è un numero', () => { expect({ id: generateId() }).toEqual({ id: expect.any(Number) }); });
expect.arrayContaining
Tipo:
<T>(expected: T[]) => anySe utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
truese il valore è un array e contiene tutti gli elementi specificati.tsimport { expect, test } from 'vitest'; test('il cesto contiene la varietà Fuji', () => { const basket = { varieties: ['Empire', 'Fuji', 'Gala'], count: 3, }; expect(basket).toEqual({ count: 3, varieties: expect.arrayContaining(['Fuji']), }); });TIP
È possibile utilizzare
expect.notcon questo matcher per negare il valore previsto.
expect.objectContaining
Tipo:
(expected: any) => anySe utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
truese il valore è un oggetto e contiene almeno le proprietà specificate con i valori corrispondenti.tsimport { expect, test } from 'vitest'; test('il cesto ha mele empire', () => { const basket = { varieties: [ { name: 'Empire', count: 1, }, ], }; expect(basket).toEqual({ varieties: [expect.objectContaining({ name: 'Empire' })], }); });TIP
È possibile utilizzare
expect.notcon questo matcher per negare il valore previsto.
expect.stringContaining
Tipo:
(expected: any) => anySe utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
truese il valore è una stringa e contiene la sottostringa specificata.tsimport { expect, test } from 'vitest'; test("il nome della varietà contiene 'Emp'", () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringContaining('Emp'), count: 1, }); });TIP
È possibile utilizzare
expect.notcon questo matcher per negare il valore previsto.
expect.stringMatching
Tipo:
(expected: any) => anySe utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
truese il valore è una stringa e corrisponde all'espressione regolare specificata.tsimport { expect, test } from 'vitest'; test("il nome della varietà termina con 're'", () => { const variety = { name: 'Empire', count: 1, }; expect(variety).toEqual({ name: expect.stringMatching(/re$/), count: 1, }); });TIP
È possibile utilizzare
expect.notcon questo matcher per negare il valore previsto.
expect.addSnapshotSerializer
Tipo:
(plugin: PrettyFormatPlugin) => voidQuesto metodo aggiunge serializzatori personalizzati che vengono utilizzati durante la creazione di uno snapshot. Questa è una funzionalità avanzata: per maggiori informazioni, consultare la guida sui serializzatori personalizzati.
Se si aggiungono serializzatori personalizzati, è necessario chiamare questo metodo all'interno di
setupFiles. Questo influirà su ogni snapshot.TIP
Se in precedenza si utilizzava Vue CLI con Jest, si potrebbe voler installare jest-serializer-vue. Altrimenti, gli snapshot verranno racchiusi in una stringa, il che farà sì che
"venga sottoposto a escape.
expect.extend
Tipo:
(matchers: MatchersObject) => voidPermette di estendere i matcher predefiniti con matcher personalizzati. Questa funzione viene utilizzata per estendere l'oggetto matcher con nuovi matcher.
Quando si definiscono i matcher in questo modo, si creano anche dei matcher asimmetrici che possono essere utilizzati come
expect.stringContaining.tsimport { expect, test } from 'vitest'; test('matcher personalizzati', () => { expect.extend({ toBeFoo: (received, expected) => { if (received !== 'foo') { return { message: () => `ci si aspettava che ${received} fosse foo`, pass: false, }; } }, }); expect('foo').toBeFoo(); expect({ foo: 'foo' }).toEqual({ foo: expect.toBeFoo() }); });TIP
Se si vuole che i matcher personalizzati siano disponibili in ogni test, è necessario chiamare questo metodo all'interno di
setupFiles.Questa funzione mantiene la compatibilità con
expect.extenddi Jest, quindi qualsiasi libreria che la utilizza per creare matcher personalizzati funzionerà con Vitest.Se si utilizza TypeScript, a partire da Vitest 0.31.0 è possibile estendere l'interfaccia
Assertionpredefinita in un file di dichiarazione ambient (ad esempio:vitest.d.ts) con il codice seguente:tsinterface CustomMatchers<R = unknown> { toBeFoo(): R; } declare module 'vitest' { interface Assertion<T = any> extends CustomMatchers<T> {} interface AsymmetricMatchersContaining extends CustomMatchers {} }WARNING
Non dimenticare di includere il file di dichiarazione ambient nel tuo
tsconfig.json.TIP
Per maggiori informazioni, consultare la guida sull'estensione dei matcher.