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 jest
Questo 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 jest
toBe
Tipo:
(value: any) => Awaitable<void>
toBe
può 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
toBe
con numeri in virgola mobile. Poiché JavaScript li approssima,0.1 + 0.2
non è esattamente0.3
. Per asserire in modo affidabile numeri in virgola mobile, usa l'asserzionetoBeCloseTo
.
toBeCloseTo
Tipo:
(value: number, numDigits?: number) => Awaitable<void>
Usa
toBeCloseTo
per confrontare numeri in virgola mobile. L'argomento opzionalenumDigits
limita 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>
toBeDefined
asserisce 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
,toBeUndefined
verifica 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>
toBeTruthy
asserisce 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.getInfo
sarà 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
,undefined
eNaN
.
toBeFalsy
Tipo:
() => Awaitable<void>
toBeFalsy
asserisce 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.stockFailed
sarà 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
,undefined
eNaN
.
toBeNull
Tipo:
() => Awaitable<void>
toBeNull
verifica 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>
toBeNaN
verifica 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>
toBeTypeOf
verifica 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>
toBeInstanceOf
verifica 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>
toBeGreaterThan
verifica 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>
toBeGreaterThanOrEqual
verifica 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>
toBeLessThan
verifica 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>
toBeLessThanOrEqual
verifica 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>
toEqual
verifica se un valore è uguale a un altro, o se ha la stessa struttura nel caso di oggetti (confronto ricorsivo). Puoi vedere la differenza tratoEqual
etoBe
in 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>
toStrictEqual
verifica 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à
undefined
vengono 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
a
eb
non sarà uguale a un oggetto letterale con campia
eb
.
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>
toContain
verifica se un array contiene un determinato valore.toContain
può 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>
toContainEqual
verifica se un array contiene un elemento con una specifica struttura e valori. Funziona cometoEqual
all'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>
toHaveLength
verifica se un oggetto ha una proprietà.length
con 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>
toHaveProperty
verifica 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>
toMatch
verifica 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>
toMatchObject
verifica 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
arrayContaining
che 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:
toThrow
toThrowError
verifica 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) => void
Questo metodo verifica che un valore corrisponda all'ultimo snapshot salvato.
È possibile fornire una stringa
hint
opzionale 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 bloccoit
o test. Vitest ordina gli snapshot per nome nel file.snap
associato.TIP
Quando lo snapshot non corrisponde e causa il fallimento del test, se la mancata corrispondenza è prevista, è possibile premere
u
per aggiornare lo snapshot. In alternativa, è possibile passare le opzioni CLI-u
o--update
per 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) => void
Questo 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.snap
esterno).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
await
contoMatchFileSnapshot()
.
toThrowErrorMatchingSnapshot
Tipo:
(message?: string) => void
Funziona 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) => void
Funziona 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>
resolves
semplifica 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>
rejects
semplifica 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) => void
Verifica 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
assertions
con test asincroni concorrenti, è necessario utilizzareexpect
dal Contesto di test locale per garantire che venga rilevato il test corretto.
expect.hasAssertions
Tipo:
() => void
Verifica 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) => never
Questo 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 cartellasrc
e 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:
() => any
Questo 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) => any
Questo matcher asimmetrico, se utilizzato in un controllo di uguaglianza, restituirà
true
solo 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[]) => any
Se utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
true
se 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.not
con questo matcher per negare il valore previsto.
expect.objectContaining
Tipo:
(expected: any) => any
Se utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
true
se 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.not
con questo matcher per negare il valore previsto.
expect.stringContaining
Tipo:
(expected: any) => any
Se utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
true
se 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.not
con questo matcher per negare il valore previsto.
expect.stringMatching
Tipo:
(expected: any) => any
Se utilizzato in un controllo di uguaglianza, questo matcher asimmetrico restituirà
true
se 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.not
con questo matcher per negare il valore previsto.
expect.addSnapshotSerializer
Tipo:
(plugin: PrettyFormatPlugin) => void
Questo 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) => void
Permette 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.extend
di 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
Assertion
predefinita 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.