Skip to content
Vitest 3
Main Navigation Průvodce & APIKonfiguraceRežim prohlížečePokročilé API
3.2.0
2.1.9
1.6.1
0.34.6

čeština

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

čeština

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

Vzhled

Sidebar Navigation

Úvod

Proč Vitest

Začínáme

Funkce

Konfigurace Vitestu

API

Testovací reference API

Mockovací funkce

Vi

expect

expectTypeOf

assert

assertType

Průvodce

Rozhraní příkazového řádku

Filtrování testů

Testovací projekty

Generátory zpráv

Pokrytí kódu

Snímky

Mockování

Paralelní zpracování

Typové testování

Vitest UI

Testování přímo ve zdrojovém kódu

Testovací kontext

Anotace testů

Testovací prostředí

Rozšíření matcherů

Integrace s IDE

Ladění

Běžné chyby

Průvodce migrací

Migrace na Vitest 3.0

Migrace z Jest

Výkon

Profilování výkonu testů

Zlepšení výkonu

Režim prohlížeče

Rozšířené API

Srovnání

Na této stránce

Mockování ​

Při psaní testů je často nutné vytvořit „falešnou“ verzi interní nebo externí služby. Tento proces se obvykle nazývá mockování. Vitest poskytuje pomocné funkce pro mockování prostřednictvím svého nástroje vi. Můžete jej importovat z vitest nebo k němu přistupovat globálně, pokud je povolena konfigurace globals.

WARNING

Vždy pamatujte na to, že je třeba mocky vymazat nebo obnovit před nebo po každém spuštění testu, abyste zrušili změny stavu mocků mezi jednotlivými spuštěními! Další informace naleznete v dokumentaci mockReset.

Pokud nejste obeznámeni s metodami vi.fn, vi.mock nebo vi.spyOn, nejprve si projděte sekci API.

Datum a čas ​

Někdy je potřeba mít kontrolu nad systémovým datem a časem, aby byla zajištěna konzistence testování. Vitest používá balíček @sinonjs/fake-timers pro manipulaci s časovači i se systémovým datem. Více o konkrétním API naleznete podrobně zde.

Příklad ​

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(() => {
    // informujte Vitest, že používáme mockovaný čas
    vi.useFakeTimers();
  });

  afterEach(() => {
    // obnovení data po každém spuštění testu
    vi.useRealTimers();
  });

  it('allows purchases within business hours', () => {
    // nastavit hodinu v rámci pracovní doby
    const date = new Date(2000, 1, 1, 13);
    vi.setSystemTime(date);

    // volání Date.now() vrátí výše nastavené datum
    expect(purchase()).toEqual({ message: 'Success' });
  });

  it('disallows purchases outside of business hours', () => {
    // nastavit hodinu mimo pracovní dobu
    const date = new Date(2000, 1, 1, 19);
    vi.setSystemTime(date);

    // volání Date.now() vrátí výše nastavené datum
    expect(purchase()).toEqual({ message: 'Error' });
  });
});

Funkce ​

Mockování funkcí lze rozdělit do dvou kategorií: sledování a mockování.

Někdy stačí ověřit, zda byla volána konkrétní funkce (a případně jaké argumenty byly předány). V těchto případech by nám stačil špeh, který můžete použít přímo s vi.spyOn() (více si přečtěte zde).

Špehové vám však mohou pomoci pouze sledovat funkce, ale nejsou schopni změnit jejich implementaci. V případě, že potřebujeme vytvořit falešnou (nebo mockovanou) verzi funkce, můžeme použít vi.fn() (více si přečtěte zde).

Jako základ pro mockování funkcí používáme Tinyspy, ale máme vlastní obal, aby byl kompatibilní s jest. Jak vi.fn(), tak vi.spyOn() sdílejí stejné metody, nicméně pouze výsledek vrácený z vi.fn() lze volat.

Příklad ​

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

const messages = {
  items: [
    { message: 'Simple test message', from: 'Testman' },
    // ...
  ],
  getLatest, // může být také `getter nebo setter (pokud je podporován)`
};

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

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

  it('should get the latest message with a 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('should get with a 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);
  });
});

Více ​

  • Jest's Mock Functions

Globální proměnné ​

Globální proměnné, které nejsou přítomny v jsdom nebo node, můžete mockovat pomocí nástroje vi.stubGlobal. Ten vloží hodnotu globální proměnné do objektu 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);

// nyní k němu můžete přistupovat jako `IntersectionObserver` nebo `window.IntersectionObserver`

Moduly ​

Mockování modulů umožňuje sledovat knihovny třetích stran, které jsou volány v jiném kódu, což vám umožňuje testovat argumenty, výstup nebo dokonce předefinovat jejich implementaci.

Podrobnější popis API naleznete v sekci API vi.mock().

Algoritmus automatického mockování ​

Pokud váš kód importuje mockovaný modul bez jakéhokoli přidruženého souboru __mocks__ nebo tovární funkce pro tento modul, Vitest modul sám mockuje tím, že jej vyvolá a napodobí každý export.

Platí následující principy:

  • Všechna pole budou vyprázdněna
  • Všechny primitivní typy a kolekce zůstanou stejné
  • Všechny objekty budou hluboce klonovány
  • Všechny instance tříd a jejich prototypy budou hluboce klonovány

Virtuální moduly ​

Vitest podporuje mockování Vite virtuálních modulů. Funguje to jinak, než jak jsou virtuální moduly zpracovávány v Jestu. Namísto předání virtual: true funkci vi.mock musíte Vite říct, že modul existuje, jinak selže během parsování. Toho můžete dosáhnout několika způsoby:

  1. Nastavte alias
ts
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
});
  1. Poskytněte plugin, který řeší virtuální modul
ts
import { defineConfig } from 'vitest/config';
export default defineConfig({
  plugins: [
    {
      name: 'virtual-modules',
      resolveId(id) {
        if (id === '$app/forms') {
          return 'virtual:$app/forms';
        }
      },
    },
  ],
});

Výhodou druhého přístupu je, že můžete dynamicky vytvářet různé virtuální vstupní body. Pokud přesměrujete-li několik virtuálních modulů do jednoho souboru, pak všechny budou ovlivněny vi.mock, takže se ujistěte, že používáte jedinečné identifikátory.

Úskalí mockování ​

Upozorňujeme, že není možné mockovat volání metod, které jsou volány uvnitř jiných metod stejného souboru. Například v tomto kódu:

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

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

Není možné mockovat metodu foo zvenčí, protože je přímo odkazována. Takže tento kód nebude mít žádný vliv na volání foo uvnitř foobar (ale ovlivní volání foo v jiných modulech):

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

// toto ovlivní pouze "foo" mimo původní modul
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
  return {
    ...(await importOriginal<typeof import('./foobar.js')>()),
    // toto ovlivní pouze "foo" mimo původní modul
    foo: () => 'mocked',
  };
});

Toto chování můžete potvrdit poskytnutím implementace metodě foobar přímo:

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

vi.spyOn(mod, 'foo');

// exportovaná foo odkazuje na mockovanou metodu
mod.foobar(mod.foo);
ts
export function foo() {
  return 'foo';
}

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

Toto je očekávané chování. Obvykle je to známka špatného kódu, když se mockování používá takovýmto způsobem. Zvažte refaktorování kódu do více souborů nebo zlepšení architektury vaší aplikace pomocí technik, jako je dependency injection.

Příklad ​

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

// získat úkoly
export async function getTodos(event, context) {
  const client = new Client({
    // ...možnosti klienta
  });

  await client.connect();

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

    client.end();

    return success({
      message: `${result.rowCount} položka(y) vrácena`,
      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('získání seznamu úkolů', () => {
  let client;

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

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

  it('should return items successfully', 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 položka(y) vrácena',
      data: [],
      status: true,
    });
  });

  it('should throw an error', async () => {
    const mError = new Error('Nelze načíst řádky');
    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 });
  });
});

Souborový systém ​

Mockování souborového systému zajišťuje, že testy nezávisí na skutečném souborovém systému, čímž se testy stávají spolehlivějšími a předvídatelnějšími. Tato izolace pomáhá předcházet vedlejším účinkům z předchozích testů. Umožňuje testování chybových stavů a okrajových případů, které by mohly být obtížné nebo nemožné replikovat se skutečným souborovým systémem, jako jsou problémy s oprávněními, situace plného disku nebo chyby čtení/zápisu.

Vitest přímo neposkytuje žádné API pro mockování souborového systému. Můžete použít vi.mock k ručnímu mockování modulu fs, ale je to obtížné udržovat. Místo toho doporučujeme použít memfs. memfs vytváří souborový systém v paměti, který simuluje operace souborového systému bez dotyku skutečného disku. Tento přístup je rychlý a bezpečný, vyhýbá se jakýmkoli potenciálním vedlejším účinkům na skutečný souborový systém.

Příklad ​

Chcete-li automaticky přesměrovat každé volání fs na memfs, můžete vytvořit soubory __mocks__/fs.cjs a __mocks__/fs/promises.cjs v kořenovém adresáři vašeho projektu:

ts
// můžeme také použít `import`, ale pak
// každý export by měl být explicitně definován

const { fs } = require('memfs');
module.exports = fs;
ts
// můžeme také použít `import`, ale pak
// každý export by měl být explicitně definován

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';

// řekněte vitestu, aby použil simulaci fs ze složky __mocks__
// toto lze provést v souboru nastavení, pokud by fs měl být vždy mockován
vi.mock('node:fs');
vi.mock('node:fs/promises');

beforeEach(() => {
  // resetovat stav in-memory fs
  vol.reset();
});

it('should return correct text', () => {
  const path = '/hello-world.txt';
  fs.writeFileSync(path, 'hello world');

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

it('can return a value multiple times', () => {
  // můžete použít vol.fromJSON k definování několika souborů
  vol.fromJSON(
    {
      './dir1/hw.txt': 'hello dir1',
      './dir2/hw.txt': 'hello dir2',
    },
    // výchozí cwd
    '/tmp'
  );

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

Požadavky ​

Protože Vitest běží v Node.js, mockování síťových požadavků je složité; webová API nejsou k dispozici, takže potřebujeme něco, co za nás bude simulovat síťové chování. K tomu doporučujeme Mock Service Worker. Umožňuje mockovat http, WebSocket a GraphQL síťové požadavky a je nezávislý na frameworku.

Mock Service Worker (MSW) funguje tak, že zachycuje požadavky prováděné vašimi testy, což vám umožňuje jej používat bez změny jakéhokoli kódu vaší aplikace. V prohlížeči k tomu používá Service Worker API. V Node.js a pro Vitest používá knihovnu @mswjs/interceptors. Chcete-li se dozvědět více o MSW, přečtěte si jejich úvod

Konfigurace ​

Můžete jej použít jako níže ve vašem souboru nastavení

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);

// Spuštění serveru před všemi testy
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Zavření serveru po všech testech
afterAll(() => server.close());

// Resetování handlerů po každém testu pro izolaci 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);

// Spuštění serveru před všemi testy
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Zavření serveru po všech testech
afterAll(() => server.close());

// Resetování handlerů po každém testu pro izolaci 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('Zpráva přijata od klienta:', event.data);
      // Odeslat přijatou zprávu zpět klientovi
      client.send(`Server přijal: ${event.data}`);
    });
  }),
];

const server = setupServer(...wsHandlers);

// Spuštění serveru před všemi testy
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));

// Zavření serveru po všech testech
afterAll(() => server.close());

// Resetování handlerů po každém testu pro izolaci testů
afterEach(() => server.resetHandlers());

Konfigurace serveru s onUnhandledRequest: 'error' zajišťuje, že se vyhodí chyba, kdykoli dojde k požadavku, který nemá odpovídající obsluhu požadavku.

Více ​

MSW toho umí mnohem víc. Můžete přistupovat k cookies a parametrům dotazu, definovat mockované chybové odpovědi a mnoho dalšího! Chcete-li vidět vše, co můžete s MSW dělat, přečtěte si jejich dokumentaci.

Časovače ​

Když testujeme kód, který zahrnuje časové limity nebo intervaly, namísto toho, abychom nechali naše testy čekat na vypršení časového limitu, můžeme naše testy urychlit použitím „falešných“ časovačů, které mockují volání setTimeout a setInterval.

Podrobnější popis API naleznete v sekci API vi.useFakeTimers.

Příklad ​

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

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

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

const mock = vi.fn(() => console.log('spuštěno'));

describe('zpožděné provedení', () => {
  beforeEach(() => {
    vi.useFakeTimers();
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });
  it('should execute the function', () => {
    executeAfterTwoHours(mock);
    vi.runAllTimers();
    expect(mock).toHaveBeenCalledTimes(1);
  });
  it('should not execute the function', () => {
    executeAfterTwoHours(mock);
    // posunutí o 2ms nespustí funkci
    vi.advanceTimersByTime(2);
    expect(mock).not.toHaveBeenCalled();
  });
  it('should execute every minute', () => {
    executeEveryMinute(mock);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(1);
    vi.advanceTimersToNextTimer();
    expect(mock).toHaveBeenCalledTimes(2);
  });
});

Třídy ​

Celou třídu můžete mockovat jediným voláním vi.fn – jelikož všechny třídy jsou také funkce, funguje to automaticky. Mějte na paměti, že Vitest v současné době nerespektuje klíčové slovo new, takže new.target je v těle funkce vždy undefined.

ts
class Dog {
  name: string;

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

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

  greet = (): string => {
    return `Ahoj! Jmenuji se ${this.name}!`;
  };

  speak(): string {
    return 'štěk!';
  }

  isHungry() {}
  feed() {}
}

Tuto třídu můžeme znovu vytvořit pomocí funkcí ES5:

ts
const Dog = vi.fn(function (name) {
  this.name = name;
  // mockovat metody instance v konstruktoru, každá instance bude mít svůj vlastní sledovač
  this.greet = vi.fn(() => `Ahoj! Jmenuji se ${this.name}!`);
});

// všimněte si, že statické metody jsou mockovány přímo na funkci,
// nikoli na instanci třídy
Dog.getType = vi.fn(() => 'mocked animal');

// simulovat metody "speak" a "feed" na každé instanci třídy
// všechny instance `new Dog()` zdědí a budou sdílet tyto sledovače
Dog.prototype.speak = vi.fn(() => 'hlasité štěkání!');
Dog.prototype.feed = vi.fn();

WARNING

Pokud je z konstruktorové funkce vrácena neprimitivní hodnota, tato hodnota se stane výsledkem nového výrazu. V tomto případě nemusí být [[Prototype]] správně svázán:

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!

KDY POUŽÍT?

Obecně řečeno, třídu byste takto znovu vytvořili uvnitř továrny modulů, pokud je třída znovu exportována z jiného modulu:

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

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

Tato metoda může být také použita k předání instance třídy funkci, která přijímá stejné rozhraní:

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('can feed dogs', () => {
  const dogMax = new Dog('Max');

  feed(dogMax);

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

Nyní, když vytvoříme novou instanci třídy Dog, její metoda speak (spolu s feed a greet) je již mockována:

ts
const Cooper = new Dog('Cooper');
Cooper.speak(); // hlasité štěkání!
Cooper.greet(); // Ahoj! Jmenuji se Cooper!

// můžete použít vestavěná tvrzení k ověření platnosti volání
expect(Cooper.speak).toHaveBeenCalled();
expect(Cooper.greet).toHaveBeenCalled();

const Max = new Dog('Max');

// metody přiřazené prototypu jsou sdíleny mezi instancemi
expect(Max.speak).toHaveBeenCalled();
expect(Max.greet).not.toHaveBeenCalled();

Můžeme znovu přiřadit návratovou hodnotu pro konkrétní instanci:

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

// "vi.mocked" je nástroj pro typování, protože
// TypeScript neví, že Dog je simulovaná třída,
// obalí jakoukoli funkci do typu MockInstance<T>
// bez ověření, zda je funkce simulovaná
vi.mocked(dog.speak).mockReturnValue('haf haf');

dog.speak(); // haf haf

Pro mockování vlastnosti můžeme použít metodu vi.spyOn(dog, 'name', 'get'). To umožňuje používat tvrzení sledovače na simulované vlastnosti:

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

Stejnou metodou můžete také špehovat gettery a settery.

Přehled ​

INFO

vi v níže uvedených příkladech je importováno přímo z vitest. Můžete jej také použít globálně, pokud v konfiguraci nastavíte globals na true.

Chci…

Mockovat exportované proměnné ​

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

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

Mockovat exportovanou funkci ​

  1. Příklad s vi.mock:

WARNING

Nezapomeňte, že volání vi.mock je vyzdviženo na začátek souboru. Vždy bude provedeno před všemi importy.

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

vi.mock('./example.js', () => ({
  method: vi.fn(),
}));
  1. Příklad s vi.spyOn:
ts
import * as exports from './example.js';

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

Mockovat implementaci exportované třídy ​

  1. Příklad s vi.mock a .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 bude mít SomeClass
  1. Příklad s vi.spyOn:
ts
import * as mod from './example.js';

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

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

Sledovat objekt vrácený z funkce ​

  1. Příklad s použitím 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(),
      };
    }
    // nyní pokaždé, když se zavolá useObject(), vrátí
    // stejnou referenci na objekt
    return _cache;
  };
  return { useObject };
});

const obj = useObject();
// obj.method bylo voláno uvnitř some-path
expect(obj.method).toHaveBeenCalled();

Mockovat část modulu ​

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(); // má původní chování
mocked(); // je špehovací funkce

WARNING

Nezapomeňte, že toto mockuje pouze externí přístup. V tomto příkladu, pokud original volá mocked interně, vždy zavolá funkci definovanou v modulu, nikoli v mockovací továrně.

Mockovat aktuální datum ​

Pro mockování času Date můžete použít pomocnou funkci vi.setSystemTime. Tato hodnota se nebude automaticky obnovovat mezi různými testy.

Upozorňujeme, že použití vi.useFakeTimers také mění čas Date.

ts
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// resetovat mockovaný čas
vi.useRealTimers();

Mockovat globální proměnnou ​

Globální proměnnou můžete nastavit přiřazením hodnoty globalThis nebo pomocí nástroje vi.stubGlobal. Při použití vi.stubGlobal se hodnota nebude automaticky obnovovat mezi různými testy, pokud nepovolíte možnost konfigurace unstubGlobals nebo nezavoláte vi.unstubAllGlobals.

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

Mockovat import.meta.env ​

  1. Chcete-li změnit proměnnou prostředí, můžete jí jednoduše přiřadit novou hodnotu.

WARNING

Hodnota proměnné prostředí se nebude automaticky obnovovat mezi různými testy.

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

// můžete ji ručně obnovit v beforeEach funkci
const originalViteEnv = import.meta.env.VITE_ENV;

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

it('changes value', () => {
  import.meta.env.VITE_ENV = 'staging';
  expect(import.meta.env.VITE_ENV).toBe('staging');
});
  1. Pokud chcete hodnotu(y) automaticky obnovovat, můžete použít pomocníka vi.stubEnv s povolenou možností konfigurace unstubEnvs (nebo ručně zavolat vi.unstubAllEnvs v beforeEach předzpracování):
ts
import { expect, it, vi } from 'vitest';

// před spuštěním testů je "VITE_ENV" "test"
import.meta.env.VITE_ENV === 'test';

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

it('hodnota je obnovena před spuštěním dalšího testu', () => {
  expect(import.meta.env.VITE_ENV).toBe('test');
});
ts
export default defineConfig({
  test: {
    unstubEnvs: true,
  },
});
Pager
Předchozí stránkaSnímky
Další stránkaParalelní zpracování

Vydáno pod licencí MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/mocking

Vydáno pod licencí MIT.

Copyright (c) 2021-Present Vitest Team