Skip to content
Vitest 3
Main Navigation Guida & APIConfigurazioneModalità BrowserAPI avanzata
3.2.0
2.1.9
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

Introduzione

Perché Vitest

Per Iniziare

Caratteristiche

Configurazione di Vitest

API

Riferimento API di test

Funzioni Mock

Vi

expect

expectTypeOf

assert

assertType

Guida

Interfaccia a Riga di Comando

Filtro dei Test

Progetti di Test

Reporter

Copertura

Snapshot

Mocking

Parallelismo

Tipi di Test

Vitest UI

Test nel Codice Sorgente

Contesto di Test

Annotazioni dei Test

Ambiente di Test

Estensione dei Matcher

Integrazioni IDE

Debugging

Errori Comuni

Guida alla Migrazione

Migrazione a Vitest 3.0

Migrazione da Jest

Prestazioni

Profilazione delle prestazioni dei test

Ottimizzare le Prestazioni

Modalità Browser

API Avanzate

Confronto con Altri Test Runner

In questa pagina

Mocking ​

Quando si scrivono test, è inevitabile dover creare una versione "falsa" di un servizio, sia esso interno o esterno. Questa pratica è comunemente nota come mocking. Vitest offre funzioni di utilità per facilitare questo processo tramite il suo helper vi. È possibile importarlo da vitest o accedervi globalmente se la configurazione global è abilitata.

WARNING

Ricorda sempre di cancellare o ripristinare i mock prima o dopo ogni esecuzione del test per assicurare che le modifiche allo stato del mock non influenzino i test successivi! Per maggiori dettagli, consulta la documentazione di mockReset.

Se non hai familiarità con i metodi vi.fn, vi.mock o vi.spyOn, ti consigliamo di consultare prima la sezione API.

Date ​

A volte è necessario controllare la data per garantire la coerenza durante i test. Vitest utilizza il pacchetto @sinonjs/fake-timers per manipolare i timer e la data di sistema. Puoi trovare maggiori dettagli sull'API specifica qui.

Esempio ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

const businessHours = [9, 17];

function purchase() {
  const currentHour = new Date().getHours();
  const [open, close] = businessHours;

  if (currentHour > open && currentHour < close) {
    return { message: 'Success' };
  }

  return { message: 'Error' };
}

describe('purchasing flow', () => {
  beforeEach(() => {
    // indica a Vitest di usare i timer fittizi
    vi.useFakeTimers();
  });

  afterEach(() => {
    // ripristina i timer reali dopo ogni esecuzione del test
    vi.useRealTimers();
  });

  it('consente gli acquisti durante l\'orario lavorativo', () => {
    // imposta l'ora all'interno dell'orario di lavoro
    const date = new Date(2000, 1, 1, 13);
    vi.setSystemTime(date);

    // l'accesso a Date.now() risulterà nella data impostata sopra
    expect(purchase()).toEqual({ message: 'Success' });
  });

  it('non permette acquisti fuori dall\'orario lavorativo', () => {
    // imposta l'ora al di fuori dell'orario di lavoro
    const date = new Date(2000, 1, 1, 19);
    vi.setSystemTime(date);

    // l'accesso a Date.now() risulterà nella data impostata sopra
    expect(purchase()).toEqual({ message: 'Error' });
  });
});

Funzioni ​

Il mocking delle funzioni può essere suddiviso in due categorie principali: spying e mocking.

A volte è sufficiente convalidare se una funzione specifica è stata chiamata (e quali argomenti sono stati passati). In questi casi, una "spy" è sufficiente e può essere utilizzata direttamente con vi.spyOn() (leggi di più qui).

Tuttavia, le "spy" possono solo spiare le funzioni; non sono in grado di modificarne l'implementazione. Nel caso in cui sia necessario creare una versione fittizia (o mockata) di una funzione, possiamo usare vi.fn() (leggi di più qui).

Utilizziamo Tinyspy come base per il mocking delle funzioni, ma abbiamo un nostro wrapper per renderlo compatibile con jest. Sia vi.fn() che vi.spyOn() condividono gli stessi metodi, tuttavia solo il risultato di vi.fn() è eseguibile.

Esempio ​

js
import { afterEach, describe, expect, it, vi } from 'vitest';

const messages = {
  items: [
    { message: 'Simple test message', from: 'Testman' },
    // ...
  ],
  getLatest, // può anche essere un "getter" o un "setter", se supportati
};

function getLatest(index = messages.items.length - 1) {
  return messages.items[index];
}

describe('reading messages', () => {
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it('dovrebbe recuperare l\'ultimo messaggio utilizzando uno spy', () => {
    const spy = vi.spyOn(messages, 'getLatest');
    expect(spy.getMockName()).toEqual('getLatest');

    expect(messages.getLatest()).toEqual(
      messages.items[messages.items.length - 1]
    );

    expect(spy).toHaveBeenCalledTimes(1);

    spy.mockImplementationOnce(() => 'access-restricted');
    expect(messages.getLatest()).toEqual('access-restricted');

    expect(spy).toHaveBeenCalledTimes(2);
  });

  it('dovrebbe ottenere con un mock', () => {
    const mock = vi.fn().mockImplementation(getLatest);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(1);

    mock.mockImplementationOnce(() => 'access-restricted');
    expect(mock()).toEqual('access-restricted');

    expect(mock).toHaveBeenCalledTimes(2);

    expect(mock()).toEqual(messages.items[messages.items.length - 1]);
    expect(mock).toHaveBeenCalledTimes(3);
  });
});

Altro ​

  • Funzioni Mock di Jest

Variabili globali ​

Puoi mockare le variabili globali non presenti con jsdom o node usando l'utilità vi.stubGlobal. Questo inserirà il valore della variabile globale in un oggetto globalThis.

ts
import { vi } from 'vitest';

const IntersectionObserverMock = vi.fn(() => ({
  disconnect: vi.fn(),
  observe: vi.fn(),
  takeRecords: vi.fn(),
  unobserve: vi.fn(),
}));

vi.stubGlobal('IntersectionObserver', IntersectionObserverMock);

// ora puoi accedervi come `IntersectionObserver` o `window.IntersectionObserver`

Moduli ​

I moduli mock interagiscono con le librerie di terze parti invocate in altro codice, permettendoti di testare argomenti, output o persino di ridefinirne l'implementazione.

Consulta la sezione API di vi.mock() per una descrizione API più dettagliata e approfondita.

Algoritmo di Automocking ​

Se il tuo codice importa un modulo mockato, senza alcun file __mocks__ associato o una factory per tale modulo, Vitest mockerà il modulo stesso invocandolo e mockando ogni export.

Si applicano i seguenti principi:

  • Tutti gli array saranno svuotati
  • Tutti i tipi primitivi e le collezioni rimarranno invariati
  • Tutti gli oggetti saranno clonati profondamente
  • Tutte le istanze di classi e i loro prototipi saranno clonati profondamente

Moduli Virtuali ​

Vitest supporta il mocking dei moduli virtuali di Vite. Funziona in modo diverso da come i moduli virtuali sono trattati in Jest. Invece di passare l'opzione virtual: true a una funzione vi.mock, devi indicare a Vite che il modulo esiste, altrimenti si verificherà un errore durante il parsing. Puoi farlo in diversi modi:

  1. Fornire un alias
ts
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
});
  1. Fornire un plugin che risolve un modulo virtuale
ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
  plugins: [
    {
      name: 'virtual-modules',
      resolveId(id) {
        if (id === '$app/forms') {
          return 'virtual:$app/forms';
        }
      },
    },
  ],
});

Il vantaggio del secondo approccio è che puoi creare dinamicamente diversi "entrypoint" virtuali. Se reindirizzi diversi moduli virtuali in un singolo file, allora ne saranno tutti influenzati da vi.mock, quindi assicurati di usare identificatori unici.

Insidie del Mocking ​

Si noti che non è possibile mockare le chiamate a metodi che vengono invocati all'interno di altri metodi dello stesso file. Ad esempio, in questo codice:

ts
export function foo() {
  return 'foo';
}

export function foobar() {
  return `${foo()}bar`;
}

Non è possibile mockare il metodo foo dall'esterno perché è referenziato direttamente. Di conseguenza, questo codice non avrà alcun effetto sulla chiamata a foo all'interno di foobar (ma avrà effetto sulla chiamata a foo in altri moduli):

ts
import { vi } from 'vitest';
import * as mod from './foobar.js';

// questo avrà effetto soltanto su "foo" al di fuori del modulo originale
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
  return {
    ...(await importOriginal<typeof import('./foobar.js')>()),
    // questo avrà effetto soltanto su "foo" al di fuori del modulo originale
    foo: () => 'mocked',
  };
});

Puoi confermare questo comportamento fornendo l'implementazione al metodo foobar direttamente:

ts
import * as mod from './foobar.js';

vi.spyOn(mod, 'foo');

// foo esportato fa riferimento al metodo mockato
mod.foobar(mod.foo);
ts
export function foo() {
  return 'foo';
}

export function foobar(injectedFoo) {
  return injectedFoo === foo; // false
}

Questo è il comportamento previsto. Di solito è un segno di codice di scarsa qualità quando il mocking è coinvolto in questo modo. Si consiglia di rifattorizzare il codice in più file o di migliorare l'architettura dell'applicazione utilizzando tecniche come l'iniezione di dipendenza.

Esempio ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { Client } from 'pg';
import { failure, success } from './handlers.js';

// ottieni i todo
export async function getTodos(event, context) {
  const client = new Client({
    // ...opzioni del client
  });

  await client.connect();

  try {
    const result = await client.query('SELECT * FROM todos;');

    client.end();

    return success({
      message: `${result.rowCount} elementi restituiti`,
      data: result.rows,
      status: true,
    });
  } catch (e) {
    console.error(e.stack);

    client.end();

    return failure({ message: e, status: false });
  }
}

vi.mock('pg', () => {
  const Client = vi.fn();
  Client.prototype.connect = vi.fn();
  Client.prototype.query = vi.fn();
  Client.prototype.end = vi.fn();

  return { Client };
});

vi.mock('./handlers.js', () => {
  return {
    success: vi.fn(),
    failure: vi.fn(),
  };
});

describe('ottieni una lista di elementi todo', () => {
  let client;

  beforeEach(() => {
    client = new Client();
  });

  afterEach(() => {
    vi.clearAllMocks();
  });

  it('dovrebbe restituire gli elementi con successo', async () => {
    client.query.mockResolvedValueOnce({ rows: [], rowCount: 0 });

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);

    expect(success).toBeCalledWith({
      message: '0 elementi restituiti',
      data: [],
      status: true,
    });
  });

  it('dovrebbe lanciare un errore', async () => {
    const mError = new Error('Impossibile recuperare le righe');
    client.query.mockRejectedValueOnce(mError);

    await getTodos();

    expect(client.connect).toBeCalledTimes(1);
    expect(client.query).toBeCalledWith('SELECT * FROM todos;');
    expect(client.end).toBeCalledTimes(1);
    expect(failure).toBeCalledWith({ message: mError, status: false });
  });
});

File System ​

Il mocking del file system assicura che i test non dipendano dal file system reale, rendendo i test più affidabili e prevedibili. Questo isolamento aiuta a evitare effetti collaterali da test precedenti. Permette di testare condizioni di errore e casi limite che potrebbero essere difficili o impossibili da replicare con un file system reale, come problemi di permessi, scenari di disco pieno o errori di lettura/scrittura.

Vitest non fornisce alcuna API di mocking del file system pronta all'uso. Puoi usare vi.mock per mockare il modulo fs manualmente, ma è di difficile manutenzione. Invece, ti consigliamo di usare memfs per farlo. memfs crea un file system in memoria, che simula le operazioni del file system senza toccare il disco reale. Questo approccio è veloce e sicuro, evitando potenziali effetti collaterali sul file system reale.

Esempio ​

Per reindirizzare automaticamente ogni chiamata fs a memfs, puoi creare i file __mocks__/fs.cjs e __mocks__/fs/promises.cjs nella root del tuo progetto:

ts
// possiamo anche usare `import`, ma poi
// ogni esportazione dovrebbe essere esplicitamente definita

const { fs } = require('memfs');
module.exports = fs;
ts
// possiamo anche usare `import`, ma poi
// ogni esportazione dovrebbe essere esplicitamente definita

const { fs } = require('memfs');
module.exports = fs.promises;
ts
import { readFileSync } from 'node:fs';

export function readHelloWorld(path) {
  return readFileSync(path, 'utf-8');
}
ts
import { beforeEach, expect, it, vi } from 'vitest';
import { fs, vol } from 'memfs';
import { readHelloWorld } from './read-hello-world.js';

// indica a Vitest di usare il mock fs dalla cartella __mocks__
// questo può essere fatto in un file di setup se fs deve essere sempre mockato
vi.mock('node:fs');
vi.mock('node:fs/promises');

beforeEach(() => {
  // resetta lo stato del fs in memoria
  vol.reset();
});

it('dovrebbe restituire il testo corretto', () => {
  const path = '/hello-world.txt';
  fs.writeFileSync(path, 'hello world');

  const text = readHelloWorld(path);
  expect(text).toBe('hello world');
});

it('può restituire un valore più volte', () => {
  // puoi usare vol.fromJSON per definire diversi file
  vol.fromJSON(
    {
      './dir1/hw.txt': 'hello dir1',
      './dir2/hw.txt': 'hello dir2',
    },
    // cwd predefinito
    '/tmp'
  );

  expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1');
  expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2');
});

Richieste ​

Poiché Vitest viene eseguito in Node, il mocking delle richieste di rete è complesso. Le API web non sono disponibili, quindi abbiamo bisogno di qualcosa che simuli il comportamento di rete per noi. Raccomandiamo Mock Service Worker per raggiungere questo obiettivo. Ti consente di mockare richieste di rete http, WebSocket e GraphQL, ed è indipendente dal framework.

Mock Service Worker (MSW) funziona intercettando le richieste che i tuoi test effettuano, permettendoti di usarlo senza modificare il codice della tua applicazione. Nel browser, viene utilizzata l'API Service Worker. In Node.js, e per Vitest, si avvale della libreria @mswjs/interceptors. Per saperne di più su MSW, leggi la loro introduzione

Configurazione ​

Puoi usarlo come segue nel tuo file di setup

js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { http, HttpResponse } from 'msw';

const posts = [
  {
    userId: 1,
    id: 1,
    title: 'first post title',
    body: 'first post body',
  },
  // ...
];

export const restHandlers = [
  http.get('https://rest-endpoint.example/path/to/posts', () => {
    return HttpResponse.json(posts);
  }),
];

const server = setupServer(...restHandlers);

// Avvia il server prima di tutti i test
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Chiudi il server dopo tutti i test
afterAll(() => server.close());

// Resetta i gestori dopo ogni test per garantire l'isolamento dei test
afterEach(() => server.resetHandlers());
js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { graphql, HttpResponse } from 'msw';

const posts = [
  {
    userId: 1,
    id: 1,
    title: 'first post title',
    body: 'first post body',
  },
  // ...
];

const graphqlHandlers = [
  graphql.query('ListPosts', () => {
    return HttpResponse.json({
      data: { posts },
    });
  }),
];

const server = setupServer(...graphqlHandlers);

// Avvia il server prima di tutti i test
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Chiudi il server dopo tutti i test
afterAll(() => server.close());

// Resetta i gestori dopo ogni test per garantire l'isolamento dei test
afterEach(() => server.resetHandlers());
js
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { ws } from 'msw';

const chat = ws.link('wss://chat.example.com');

const wsHandlers = [
  chat.addEventListener('connection', ({ client }) => {
    client.addEventListener('message', event => {
      console.log('Messaggio ricevuto dal client:', event.data);
      // Ripeti il messaggio ricevuto al client
      client.send(`Server ricevuto: ${event.data}`);
    });
  }),
];

const server = setupServer(...wsHandlers);

// Avvia il server prima di tutti i test
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Chiudi il server dopo tutti i test
afterAll(() => server.close());

// Resetta i gestori dopo ogni test per garantire l'isolamento dei test
afterEach(() => server.resetHandlers());

La configurazione del server con onUnhandledRequest: 'error' garantisce che venga generato un errore ogni volta che una richiesta non ha un gestore corrispondente.

Altro ​

MSW offre molte altre funzionalità. Puoi accedere ai cookie e ai parametri di query, definire risposte di errore mockate e molto altro! Per vedere tutto ciò che puoi fare con MSW, leggi la loro documentazione.

Timer ​

Quando testiamo codice che coinvolge timeout o intervalli, invece di far attendere o scadere i nostri test, possiamo accelerare i nostri test usando timer "falsi" che mockano le chiamate a setTimeout e setInterval.

Consulta la sezione API di vi.useFakeTimers per una descrizione API più dettagliata e approfondita.

Esempio ​

js
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';

function executeAfterTwoHours(func) {
  setTimeout(func, 1000 * 60 * 60 * 2); // 2 ore
}

function executeEveryMinute(func) {
  setInterval(func, 1000 * 60); // 1 minuto
}

const mock = vi.fn(() => console.log('eseguito'));

describe('esecuzione ritardata', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });
  it('dovrebbe eseguire la funzione', () => {
    executeAfterTwoHours(mock);
    vi.runAllTimers();
    expect(mock).toHaveBeenCalledTimes(1);
  });
  it('non dovrebbe eseguire la funzione', () => {
    executeAfterTwoHours(mock);
    // avanzare di 2ms non attiverà la funzione
    vi.advanceTimersByTime(2);
    expect(mock).not.toHaveBeenCalled();
  });
  it('dovrebbe eseguire ogni minuto', () => {
    executeEveryMinute(mock);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(1);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(2);
  });
});

Classi ​

Puoi mockare un'intera classe con una singola chiamata vi.fn - poiché tutte le classi sono anche funzioni, questo funziona out of the box. Si noti che attualmente Vitest non rispetta la parola chiave new, quindi new.target è sempre undefined nel corpo di una funzione.

ts
class Dog {
  name: string;

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

  static getType(): string {
    return 'animal';
  }

  greet = (): string => {
    return `Ciao! Il mio nome è ${this.name}!`;
  };

  speak(): string {
    return 'bau!';
  }

  isHungry() {}
  feed() {}
}

Possiamo ricreare questa classe con funzioni ES5:

ts
const Dog = vi.fn(function (name) {
  this.name = name;
  // mocka i metodi dell'istanza nel costruttore, ogni istanza avrà una propria spy
  this.greet = vi.fn(() => `Ciao! Il mio nome è ${this.name}!`);
});

// si noti che i metodi statici sono mockati direttamente sulla funzione,
// non sull'istanza della classe
Dog.getType = vi.fn(() => 'animale simulato');

// mocka i metodi "speak" e "feed" su ogni istanza di una classe
// tutte le istanze `new Dog()` erediteranno e condivideranno queste funzioni spy
Dog.prototype.speak = vi.fn(() => 'bau forte!');
Dog.prototype.feed = vi.fn();

WARNING

Se un valore non primitivo viene restituito dalla funzione costruttore, quel valore diventerà il risultato dell'espressione new. In questo caso il [[Prototype]] potrebbe non essere correttamente associato:

ts
const CorrectDogClass = vi.fn(function (name) {
  this.name = name;
});

const IncorrectDogClass = vi.fn(name => ({
  name,
}));

const Marti = new CorrectDogClass('Marti');
const Newt = new IncorrectDogClass('Newt');

Marti instanceof CorrectDogClass; // ✅ true
Newt instanceof IncorrectDogClass; // ❌ false!

QUANDO USARLO?

Generalmente, si ricreerebbe una classe in questo modo all'interno della factory del modulo se la classe viene riesportata da un altro modulo:

ts
import { Dog } from './dog.js';

vi.mock(import('./dog.js'), () => {
  const Dog = vi.fn();
  Dog.prototype.feed = vi.fn();
  // ... altri mock
  return { Dog };
});

Questo metodo può anche essere usato per passare un'istanza di una classe a una funzione che implementa la stessa interfaccia:

ts
function feed(dog: Dog) {
  // ...
}
ts
import { expect, test, vi } from 'vitest';
import { feed } from '../src/feed.js';

const Dog = vi.fn();
Dog.prototype.feed = vi.fn();

test('è possibile nutrire i cani', () => {
  const dogMax = new Dog('Max');

  feed(dogMax);

  expect(dogMax.feed).toHaveBeenCalled();
  expect(dogMax.isHungry()).toBe(false);
});

Ora, quando creiamo una nuova istanza della classe Dog, il suo metodo speak (insieme a feed e greet) è già mockato:

ts
const Cooper = new Dog('Cooper');
Cooper.speak(); // bau forte!
Cooper.greet(); // Ciao! Il mio nome è Cooper!

// è possibile usare le asserzioni integrate per controllare la validità della chiamata
expect(Cooper.speak).toHaveBeenCalled();
expect(Cooper.greet).toHaveBeenCalled();

const Max = new Dog('Max');

// i metodi definiti sul prototipo sono condivisi tra le istanze
expect(Max.speak).toHaveBeenCalled();
expect(Max.greet).not.toHaveBeenCalled();

Possiamo riassegnare il valore di ritorno per un'istanza specifica:

ts
const dog = new Dog('Cooper');

// "vi.mocked" è un'utilità di tipo, poiché
// TypeScript non sa che Dog è una classe mockata,
// incapsula qualsiasi funzione in un tipo MockInstance<T>
// senza convalidare se la funzione è un mock
vi.mocked(dog.speak).mockReturnValue('bau bau');

dog.speak(); // bau bau

Per mockare la proprietà, è possibile usare il metodo vi.spyOn(dog, 'name', 'get'). In questo modo è possibile usare le asserzioni spy sulla proprietà mockata:

ts
const dog = new Dog('Cooper');

const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max');

expect(dog.name).toBe('Max');
expect(nameSpy).toHaveBeenCalledTimes(1);

TIP

Puoi anche spiare getter e setter usando lo stesso metodo.

Foglio riassuntivo ​

INFO

vi negli esempi seguenti è importato direttamente da vitest. È anche possibile usarlo globalmente, se imposti globals a true nella tua configurazione.

Voglio…

Mockare variabili esportate ​

js
export const getter = 'variable';
ts
import * as exports from './example.js';

vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');

Mockare una funzione esportata ​

  1. Esempio con vi.mock:

WARNING

Si tenga presente che una chiamata vi.mock viene elevata all'inizio del file. Verrà sempre eseguita prima di tutte le importazioni.

ts
export function method() {}
ts
import { method } from './example.js';

vi.mock('./example.js', () => ({
  method: vi.fn(),
}));
  1. Esempio con vi.spyOn:
ts
import * as exports from './example.js';

vi.spyOn(exports, 'method').mockImplementation(() => {});

Mockare l'implementazione di una classe esportata ​

  1. Esempio con vi.mock e .prototype:
ts
export class SomeClass {}
ts
import { SomeClass } from './example.js';

vi.mock(import('./example.js'), () => {
  const SomeClass = vi.fn();
  SomeClass.prototype.someMethod = vi.fn();
  return { SomeClass };
});
// SomeClass.mock.instances conterrà l'istanza di SomeClass
  1. Esempio con vi.spyOn:
ts
import * as mod from './example.js';

const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();

vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass);

Spiare un oggetto restituito da una funzione ​

  1. Esempio usando la cache:
ts
export function useObject() {
  return { method: () => true };
}
ts
import { useObject } from './example.js';

const obj = useObject();
obj.method();
ts
import { useObject } from './example.js';

vi.mock(import('./example.js'), () => {
  let _cache;
  const useObject = () => {
    if (!_cache) {
      _cache = {
        method: vi.fn(),
      };
    }
    // ora ogni volta che useObject() viene chiamato,
    // restituirà lo stesso riferimento all'oggetto
    return _cache;
  };
  return { useObject };
});

const obj = useObject();
// obj.method è stato chiamato all'interno di "some-path"
expect(obj.method).toHaveBeenCalled();

Mockare parte di un modulo ​

ts
import { mocked, original } from './some-path.js';

vi.mock(import('./some-path.js'), async importOriginal => {
  const mod = await importOriginal();
  return {
    ...mod,
    mocked: vi.fn(),
  };
});
original(); // ha il comportamento originale
mocked(); // è una funzione spy

WARNING

Si tenga presente che questo mocka solo l'accesso esterno. In questo esempio, se original chiama mocked internamente, chiamerà sempre la funzione definita nel modulo, non nella factory del mock.

Mockare la data corrente ​

Per mockare l'ora di Date, puoi usare la funzione helper vi.setSystemTime. Questo valore non verrà automaticamente ripristinato tra i diversi test.

Si noti che l'uso di vi.useFakeTimers cambia anche l'ora di Date.

ts
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// resetta il tempo mockato
vi.useRealTimers();

Mockare una variabile globale ​

È possibile impostare una variabile globale assegnando un valore a globalThis o usando l'helper vi.stubGlobal. Quando si usa vi.stubGlobal, non verrà automaticamente ripristinato tra i diversi test, a meno che non si abiliti l'opzione di configurazione unstubGlobals o si chiami vi.unstubAllGlobals.

ts
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');

Mockare import.meta.env ​

  1. Per cambiare una variabile d'ambiente, è sufficiente assegnarle un nuovo valore.

WARNING

Il valore della variabile d'ambiente non verrà automaticamente ripristinato tra i diversi test.

ts
import { beforeEach, expect, it } from 'vitest';

// prima di eseguire i test "VITE_ENV" è "test"
const originalViteEnv = import.meta.env.VITE_ENV;

beforeEach(() => {
  import.meta.env.VITE_ENV = originalViteEnv;
});

it('cambia valore', () => {
  import.meta.env.VITE_ENV = 'staging';
  expect(import.meta.env.VITE_ENV).toBe('staging');
});
  1. Se si desidera resettare automaticamente i valori, è possibile usare l'helper vi.stubEnv con l'opzione di configurazione unstubEnvs abilitata (o chiamare vi.unstubAllEnvs manualmente in una funzione di hook beforeEach):
ts
import { expect, it, vi } from 'vitest';

// prima di eseguire i test "VITE_ENV" è "test"
import.meta.env.VITE_ENV === 'test';

it('cambia valore', () => {
  vi.stubEnv('VITE_ENV', 'staging');
  expect(import.meta.env.VITE_ENV).toBe('staging');
});

it('il valore viene ripristinato prima di eseguire un altro test', () => {
  expect(import.meta.env.VITE_ENV).toBe('test');
});
ts
export default defineConfig({
  test: {
    unstubEnvs: true,
  },
});
Pager
Pagina precedenteSnapshot
Pagina successivaParallelismo

Rilasciato sotto la licenza MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/mocking

Rilasciato sotto la licenza MIT.

Copyright (c) 2021-Present Vitest Team