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
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
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
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
.
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:
- Nastavte alias
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
test: {
alias: {
'$app/forms': resolve('./mocks/forms.js'),
},
},
});
- Poskytněte plugin, který řeší virtuální modul
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:
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):
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:
import * as mod from './foobar.js';
vi.spyOn(mod, 'foo');
// exportovaná foo odkazuje na mockovanou metodu
mod.foobar(mod.foo);
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
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:
// 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;
// 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;
import { readFileSync } from 'node:fs';
export function readHelloWorld(path) {
return readFileSync(path, 'utf-8');
}
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í
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());
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());
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
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
.
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:
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:
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:
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í:
function feed(dog: Dog) {
// ...
}
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:
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:
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:
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é
export const getter = 'variable';
import * as exports from './example.js';
vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');
Mockovat exportovanou funkci
- 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.
export function method() {}
import { method } from './example.js';
vi.mock('./example.js', () => ({
method: vi.fn(),
}));
- Příklad s
vi.spyOn
:
import * as exports from './example.js';
vi.spyOn(exports, 'method').mockImplementation(() => {});
Mockovat implementaci exportované třídy
- Příklad s
vi.mock
a.prototype
:
export class SomeClass {}
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
- Příklad s
vi.spyOn
:
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
- Příklad s použitím cache:
export function useObject() {
return { method: () => true };
}
import { useObject } from './example.js';
const obj = useObject();
obj.method();
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
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
.
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
.
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');
Mockovat import.meta.env
- 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.
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');
});
- Pokud chcete hodnotu(y) automaticky obnovovat, můžete použít pomocníka
vi.stubEnv
s povolenou možností konfiguraceunstubEnvs
(nebo ručně zavolatvi.unstubAllEnvs
vbeforeEach
předzpracování):
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');
});
export default defineConfig({
test: {
unstubEnvs: true,
},
});