Skip to content
Vitest 1
Main Navigation GuidaAPIConfigurazioneAvanzato
1.6.1
0.34.6

Italiano

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Polski
Türkçe
čeština
magyar

Italiano

English
简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Polski
Türkçe
čeština
magyar

Aspetto

Sidebar Navigation

Guida

Perché Vitest

Introduzione

Funzionalità

Workspace

Interfaccia a riga di comando

Filtro dei test

Reporter

Coverage

Snapshot

Mocking

Test dei Tipi

Interfaccia Utente di Vitest

Modalità Browser

Test nel codice sorgente

Contesto del Test

Ambienti di Test

Estensione dei Matchers

Integrazione con gli IDE

Debugging

Confronti con altri Test Runner

Guida alla Migrazione

Errori Frequenti

Ottimizzare le Prestazioni

API

Riferimento API Test

Funzioni Mock

Vi

expect

expectTypeOf

assert

assertType

Configurazione

Gestione del file di configurazione di Vitest

Configurazione di Vitest

In questa pagina

expect ​

I seguenti tipi sono utilizzati nelle definizioni di tipo sottostanti:

ts
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à.

ts
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.

ts
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.

ts
import { expect, test } from 'vitest';

test('expect.soft test', () => {
  expect.soft(1 + 1).toBe(3); // segnala il fallimento ma continua
  expect(1 + 2).toBe(4); // fallisce e interrompe il test, tutti gli errori precedenti verranno visualizzati
  expect.soft(1 + 3).toBe(5); // 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à.

ts
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 chiamare expect(Object.is(3, 3)).toBe(true). Se gli oggetti non sono identici, ma si vuole verificare se le loro strutture sono uguali, si può usare toEqual.

Ad esempio, il codice qui sotto controlla se il commerciante ha 13 mele.

ts
import { expect, test } from 'vitest';

const stock = {
  type: 'apples',
  count: 13,
};

test('stock has 13 apples', () => {
  expect(stock.type).toBe('apples');
  expect(stock.count).toBe(13);
});

test('stocks are the same', () => {
  const refStock = stock; // stesso riferimento

  expect(stock).toBe(refStock);
});

È consigliabile non usare toBe con numeri in virgola mobile. Poiché JavaScript li approssima, 0.1 + 0.2 non è esattamente 0.3. Per asserire in modo affidabile numeri in virgola mobile, usa l'asserzione toBeCloseTo.

toBeCloseTo ​

  • Tipo: (value: number, numDigits?: number) => Awaitable<void>

Usa toBeCloseTo per confrontare numeri in virgola mobile. L'argomento opzionale numDigits limita il numero di cifre da controllare dopo la virgola. Ad esempio:

ts
import { 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 a undefined. È utile per verificare se una funzione ha restituito un valore.

ts
import { 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 a undefined. Un caso d'uso utile è verificare se una funzione non ha restituito alcun valore.

ts
import { expect, test } from 'vitest';

function getApplesFromStock(stock: string) {
  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 in true.

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.

ts
import { 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:

ts
import { 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, null, undefined, NaN, 0, -0, 0n, "" e document.all.

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 in false.

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.

ts
import { 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:

ts
import { 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, null, undefined, NaN, 0, -0, 0n, "" e document.all.

toBeNull ​

  • Tipo: () => Awaitable<void>

toBeNull verifica semplicemente se un valore è null. Alias per .toBe(null).

ts
import { 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).

ts
import { 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.

ts
import { 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.

ts
import { 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.

ts
import { 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.

ts
import { 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.

ts
import { 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.

ts
import { 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 tra toEqual e toBe in questo esempio:

ts
import { 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

Non verrà eseguito un controllo di uguaglianza profonda per gli oggetti Error. Solo la proprietà message di un errore viene considerata per l'uguaglianza. Per personalizzare l'uguaglianza per controllare proprietà diverse da message, utilizzare expect.addEqualityTesters. Per verificare se qualcosa è stato lanciato, utilizzare l'asserzione toThrowError.

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 e b non sarà uguale a un oggetto letterale con campi a e b.
ts
import { 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' });
});

toContain ​

  • Tipo: (received: string) => Awaitable<void>

toContain asserisce se il valore effettivo è in un array. toContain può anche verificare se una stringa è una sottostringa di un'altra stringa. Da Vitest 1.0, se si eseguono test in un ambiente simile a un browser, questa asserzione può anche verificare se la classe è contenuta in una classList o se un elemento è all'interno di un altro.

ts
import { expect, test } from 'vitest';
import { getAllFruits } from './stocks.js';

test("l'elenco della frutta contiene orange", () => {
  expect(getAllFruits()).toContain('orange');

  const element = document.querySelector('#el');
  // element ha una classe
  expect(element.classList).toContain('flex');
  // element è all'interno di un altro
  expect(document.querySelector('#wrapper')).toContain(element);
});

toContainEqual ​

  • Tipo: (received: any) => Awaitable<void>

toContainEqual verifica se un array contiene un elemento con una specifica struttura e valori. Funziona come toEqual all'interno per ogni elemento.

ts
import { 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.

ts
import { 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à.

ts
import { expect, test } from 'vitest';

const invoice = {
  isActive: true,
  'P.O': '12345',
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

test('John Doe 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.

ts
import { 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
});

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.

ts
import { expect, test } from 'vitest';

const johnInvoice = {
  isActive: true,
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
  total_amount: 5000,
  items: [
    {
      type: 'apples',
      quantity: 10,
    },
    {
      type: 'oranges',
      quantity: 5,
    },
  ],
};

const johnDetails = {
  customer: {
    first_name: 'John',
    last_name: 'Doe',
    location: 'China',
  },
};

test('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:

ts
import { expect, test } from 'vitest';

function getFruitStock(type: string) {
  if (type === 'pineapples') throw new Error('Pineapples are not in stock');

  // Esegui altre operazioni
}

test('throws on pineapples', () => {
  // Verifica che il messaggio di errore contenga "stock": questi sono equivalenti
  expect(() => getFruitStock('pineapples')).toThrowError(/stock/);
  expect(() => getFruitStock('pineapples')).toThrowError('stock');

  // Verifica l'esatto messaggio di errore
  expect(() => getFruitStock('pineapples')).toThrowError(
    /^Pineapples are not in stock$/
  );
});

TIP

Per testare funzioni asincrone, utilizzare in combinazione con rejects.

js
function 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 blocco it 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.

ts
import { 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%:

ts
import { 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).

ts
import { 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%:

ts
import { 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 0.30.0+ ​

  • Tipo: <T>(filepath: string, message?: string) => Promise<void>

Confronta o aggiorna lo snapshot con il contenuto di un file specificato esplicitamente (invece del file .snap).

ts
import { 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 con toMatchFileSnapshot().

toThrowErrorMatchingSnapshot ​

  • Tipo: (message?: string) => void

Funziona come toMatchSnapshot, ma si aspetta lo stesso valore di toThrowError.

toThrowErrorMatchingInlineSnapshot ​

  • Tipo: (snapshot?: string, message?: string) => void

Funziona come toMatchInlineSnapshot, ma si aspetta lo stesso valore di toThrowError.

toHaveBeenCalled ​

  • Tipo: () => Awaitable<void>

Questa asserzione è utile per verificare se una funzione è stata chiamata. Richiede di passare una spy function a expect.

ts
import { 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.

ts
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.

ts
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.

ts
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.

ts
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.

ts
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.

ts
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.

ts
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.

ts
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.

ts
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.

ts
import { describe, expect, it } from 'vitest';
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 restituiscono Promise, quindi è necessario utilizzare await. Funziona anche con le asserzioni chai.

Ad esempio, per una funzione che effettua una chiamata API e restituisce dei dati, si può asserire il valore di ritorno in questo modo:

ts
import { 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ò utilizzare expect.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 restituiscono Promise, quindi è necessario utilizzare await. Funziona anche con le asserzioni chai.

Ad esempio, per una funzione che genera un errore, si può asserire il motivo del rifiuto in questo modo:

ts
import { 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ò utilizzare expect.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.

ts
import { 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 utilizzare expect 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.

ts
import { 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 cartella src e gestire anche ogni errore separatamente, si potrebbe fare questo:

ts
import { 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.

ts
import { 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.

ts
import { expect, test } from 'vitest';
import { generateId } from './generators.js';

test('"id" è un numero', () => {
  expect({ id: generateId() }).toEqual({ id: expect.any(Number) });
});

expect.closeTo 1.0.0+ ​

  • Tipo: (expected: any, precision?: number) => any

expect.closeTo è utile quando si confrontano numeri in virgola mobile nelle proprietà degli oggetti o negli elementi dell'array. Se devi confrontare un numero, utilizza invece .toBeCloseTo.

L'argomento opzionale numDigits limita il numero di cifre da controllare dopo la virgola decimale. Per il valore predefinito 2, il criterio di test è Math.abs(expected - received) < 0.005 (ovvero, 10 ** -2 / 2).

Ad esempio, questo test viene superato con una precisione di 5 cifre:

js
test('confronta float nelle proprietà degli oggetti', () => {
  expect({
    title: '0.1 + 0.2',
    sum: 0.1 + 0.2,
  }).toEqual({
    title: '0.1 + 0.2',
    sum: expect.closeTo(0.3, 5),
  });
});

expect.arrayContaining ​

  • 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.

ts
import { 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.

ts
import { 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.

ts
import { 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.

ts
import { 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.

ts
import { 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:

ts
interface 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.

expect.addEqualityTesters 1.2.0+ ​

  • Tipo: (tester: Array<Tester>) => void

Puoi utilizzare questo metodo per definire tester personalizzati, che sono metodi utilizzati dai matcher per verificare se due oggetti sono uguali. È compatibile con expect.addEqualityTesters di Jest.

ts
import { expect, test } from 'vitest';

class AnagramComparator {
  public word: string;

  constructor(word: string) {
    this.word = word;
  }

  equals(other: AnagramComparator): boolean {
    const cleanStr1 = this.word.replace(/ /g, '').toLowerCase();
    const cleanStr2 = other.word.replace(/ /g, '').toLowerCase();

    const sortedStr1 = cleanStr1.split('').sort().join('');
    const sortedStr2 = cleanStr2.split('').sort().join('');

    return sortedStr1 === sortedStr2;
  }
}

function isAnagramComparator(a: unknown): a is AnagramComparator {
  return a instanceof AnagramComparator;
}

function areAnagramsEqual(a: unknown, b: unknown): boolean | undefined {
  const isAAnagramComparator = isAnagramComparator(a);
  const isBAnagramComparator = isBAnagramComparator(b);

  if (isAAnagramComparator && isBAnagramComparator) return a.equals(b);
  else if (isAAnagramComparator === isBAnagramComparator) return undefined;
  else return false;
}

expect.addEqualityTesters([areAnagramsEqual]);

test('tester di uguaglianza personalizzato', () => {
  expect(new AnagramComparator('listen')).toEqual(
    new AnagramComparator('silent')
  );
});
Pager
Pagina precedenteVi
Pagina successivaexpectTypeOf

Rilasciato sotto la licenza MIT.

Copyright (c) 2024 Mithril Contributors

https://v1.vitest.dev/api/expect

Rilasciato sotto la licenza MIT.

Copyright (c) 2024 Mithril Contributors