Mockowanie
Podczas pisania testów często zachodzi potrzeba stworzenia „fałszywej” wersji wewnętrznej lub zewnętrznej usługi. Jest to powszechnie nazywane mockowaniem. Vitest dostarcza funkcji pomocniczych, aby Ci w tym pomóc, poprzez swój pomocnik vi. Możesz zaimportować vi
za pomocą import { vi } from 'vitest'
lub uzyskać do niego dostęp globalnie (gdy konfiguracja globalna jest włączona).
WARNING
Zawsze pamiętaj, aby wyczyścić lub przywrócić mocki przed lub po każdym teście, aby cofnąć zmiany stanu między uruchomieniami! Więcej informacji znajdziesz w dokumentacji mockReset
.
Jeśli chcesz od razu zagłębić się w temat, sprawdź sekcję API. W przeciwnym razie, czytaj dalej, aby głębiej zanurzyć się w świat mockowania.
Daty
Czasami musisz mieć kontrolę nad datą, aby zapewnić spójność testów. Vitest wykorzystuje pakiet @sinonjs/fake-timers
do manipulowania timerami i datą systemową. Więcej o konkretnym API znajdziesz tutaj.
Przykład
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(() => {
// informujemy Vitest, że używamy zamockowanego czasu
vi.useFakeTimers();
});
afterEach(() => {
// przywracamy datę po każdym teście
vi.useRealTimers();
});
it('allows purchases within business hours', () => {
// ustawiamy godzinę w godzinach pracy
const date = new Date(2000, 1, 1, 13);
vi.setSystemTime(date);
// dostęp do Date.now() zwróci datę ustawioną powyżej
expect(purchase()).toEqual({ message: 'Success' });
});
it('disallows purchases outside of business hours', () => {
// ustawiamy godzinę poza godzinami pracy
const date = new Date(2000, 1, 1, 19);
vi.setSystemTime(date);
// dostęp do Date.now() zwróci datę ustawioną powyżej
expect(purchase()).toEqual({ message: 'Error' });
});
});
Funkcje
Mockowanie funkcji dzieli się na dwie kategorie: szpiegowanie i mockowanie.
Czasami wystarczy sprawdzić, czy określona funkcja została wywołana (i ewentualnie jakie argumenty zostały przekazane). W takich przypadkach wystarczy szpieg, którego można użyć bezpośrednio z vi.spyOn()
(czytaj więcej tutaj).
Jednak szpiedzy mogą jedynie szpiegować funkcje; nie są w stanie zmieniać ich implementacji. W przypadku, gdy musimy stworzyć fałszywą (lub zamockowaną) wersję funkcji, możemy użyć vi.fn()
(czytaj więcej tutaj).
Używamy Tinyspy jako podstawy do mockowania funkcji, ale mamy własny wrapper, aby była kompatybilna z jest
. Zarówno vi.fn()
, jak i vi.spyOn()
mają te same metody, jednak tylko wynik zwracany przez vi.fn()
jest wywoływalny.
Przykład
import { afterEach, describe, expect, it, vi } from 'vitest';
const messages = {
items: [
{ message: 'Simple test message', from: 'Testman' },
// ...
],
getLatest, // może być również `getterem lub setterem (jeśli obsługiwany)`
};
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);
});
});
Więcej
Zmienne globalne
Możesz mockować zmienne globalne niedostępne w jsdom
lub node
, używając pomocnika vi.stubGlobal
. Umieści to wartość zmiennej globalnej w obiekcie 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);
// teraz możesz uzyskać do niego dostęp jako `IntersectionObserver` lub `window.IntersectionObserver`
Moduły
Mockowanie modułów pozwala na interakcję z bibliotekami stron trzecich, które są wywoływane w innym kodzie, umożliwiając testowanie argumentów, danych wyjściowych, a nawet ponowne deklarowanie ich implementacji.
Szczegółowy opis API znajdziesz w sekcji vi.mock()
API.
Algorytm automatycznego mockowania
Jeśli Twój kod importuje zamockowany moduł, a dla tego modułu nie ma powiązanego pliku __mocks__
ani factory
, Vitest zamockuje sam moduł, wywołując go i mockując każdy eksport.
Obowiązują następujące zasady:
- Wszystkie tablice zostaną opróżnione
- Wszystkie prymitywy i kolekcje pozostaną niezmienione
- Wszystkie obiekty zostaną głęboko sklonowane
- Wszystkie instancje klas i ich prototypy zostaną głęboko sklonowane
Moduły wirtualne
Vitest obsługuje mockowanie modułów wirtualnych Vite. Działa to inaczej niż w Jest. Zamiast przekazywać virtual: true
do funkcji vi.mock
, musisz poinformować Vite, że moduł istnieje, w przeciwnym razie wystąpi błąd podczas parsowania. Możesz to zrobić na kilka sposobów:
- Podaj alias
// vitest.config.js
export default {
test: {
alias: {
'$app/forms': resolve('./mocks/forms.js'),
},
},
};
- Dostarcz wtyczkę, która rozwiązuje moduł wirtualny
// vitest.config.js
export default {
plugins: [
{
name: 'virtual-modules',
resolveId(id) {
if (id === '$app/forms') {
return 'virtual:$app/forms';
}
},
},
],
};
Zaletą drugiego podejścia jest to, że możesz dynamicznie tworzyć różne wirtualne punkty dostępu. Jeśli przekierujesz kilka modułów wirtualnych do jednego pliku, wszystkie z nich zostaną objęte działaniem vi.mock
, więc upewnij się, że używasz unikalnych identyfikatorów.
Pułapki mockowania
Należy pamiętać, że nie można mockować wywołań metod, które są wywoływane wewnątrz innych metod tego samego pliku. Na przykład, w tym kodzie:
export function foo() {
return 'foo';
}
export function foobar() {
return `${foo()}bar`;
}
Nie jest możliwe mockowanie metody foo
z zewnątrz, ponieważ jest ona bezpośrednio odwoływana. W związku z tym ten kod nie wpłynie na wywołanie foo
wewnątrz foobar
(ale wpłynie na wywołanie foo
w innych modułach):
import { vi } from 'vitest';
import * as mod from './foobar.js';
// to wpłynie tylko na "foo" poza oryginalnym modułem
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
return {
...(await importOriginal<typeof import('./foobar.js')>()),
// to wpłynie tylko na "foo" poza oryginalnym modułem
foo: () => 'mocked',
};
});
Możesz potwierdzić to zachowanie, dostarczając implementację metody foobar
bezpośrednio:
// foobar.test.js
import * as mod from './foobar.js';
vi.spyOn(mod, 'foo');
// wyeksportowane foo odwołuje się do zamockowanej funkcji
mod.foobar(mod.foo);
// foobar.js
export function foo() {
return 'foo';
}
export function foobar(injectedFoo) {
return injectedFoo === foo; // false
}
Takie jest zamierzone zachowanie. Zazwyczaj jest to oznaka złego kodu, gdy mockowanie jest używane w ten sposób. Rozważ refaktoryzację kodu na wiele plików lub ulepszenie architektury aplikacji poprzez zastosowanie technik takich jak wstrzykiwanie zależności.
Przykład
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { Client } from 'pg';
import { failure, success } from './handlers.js';
// pobierz listę zadań
export async function getTodos(event, context) {
const client = new Client({
// ...clientOptions
});
await client.connect();
try {
const result = await client.query('SELECT * FROM todos;');
client.end();
return success({
message: `${result.rowCount} item(s) returned`,
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('get a list of todo items', () => {
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 item(s) returned',
data: [],
status: true,
});
});
it('should throw an error', async () => {
const mError = new Error('Unable to retrieve rows');
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 });
});
});
System plików
Mockowanie systemu plików zapewnia, że testy nie zależą od rzeczywistego systemu plików, czyniąc je bardziej niezawodnymi i przewidywalnymi. Ta izolacja zapobiega efektom ubocznym między testami. Pozwala na testowanie warunków błędów i przypadków brzegowych, które mogą być trudne lub niemożliwe do odtworzenia w rzeczywistym systemie plików (np. problemy z uprawnieniami, scenariusze pełnego dysku lub błędy odczytu/zapisu).
Vitest nie dostarcza żadnego API do mockowania systemu plików domyślnie. Możesz użyć vi.mock
do ręcznego mockowania modułu fs
, ale jest to trudne w utrzymaniu. Zamiast tego zalecamy użycie memfs
, aby to za Ciebie zrobić. memfs
tworzy system plików w pamięci, który symuluje operacje na systemie plików bez dotykania rzeczywistego dysku. To podejście jest szybkie i bezpieczne, pozwalając uniknąć wszelkich potencjalnych efektów ubocznych na rzeczywistym systemie plików.
Przykład
Aby automatycznie przekierować każde wywołanie fs
do memfs
, możesz utworzyć pliki __mocks__/fs.cjs
i __mocks__/fs/promises.cjs
w katalogu głównym swojego projektu:
// możemy również użyć `import`, ale wtedy
// każdy eksport powinien być jawnie zdefiniowany
const { fs } = require('memfs');
module.exports = fs;
// możemy również użyć `import`, ale wtedy
// każdy eksport powinien być jawnie zdefiniowany
const { fs } = require('memfs');
module.exports = fs.promises;
// read-hello-world.js
import { readFileSync } from 'node:fs';
export function readHelloWorld(path) {
return readFileSync(path);
}
// hello-world.test.js
import { beforeEach, expect, it, vi } from 'vitest';
import { fs, vol } from 'memfs';
import { readHelloWorld } from './read-hello-world.js';
// poinformuj vitest, aby używał mocku fs z folderu __mocks__
// można to zrobić w pliku setup, jeśli fs zawsze powinien być mockowany
vi.mock('node:fs');
vi.mock('node:fs/promises');
beforeEach(() => {
// resetuj stan systemu plików w pamięci
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', () => {
// możesz użyć vol.fromJSON, aby zdefiniować kilka plików
vol.fromJSON(
{
'./dir1/hw.txt': 'hello dir1',
'./dir2/hw.txt': 'hello dir2',
},
// domyślny cwd
'/tmp'
);
expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1');
expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2');
});
Żądania
Ponieważ Vitest działa w Node.js, mockowanie żądań sieciowych stanowi wyzwanie; API webowe nie są dostępne, więc potrzebujemy czegoś, co będzie symulować zachowanie sieciowe. Zalecamy użycie Mock Service Worker, aby to osiągnąć. Pozwoli to na mockowanie zarówno żądań sieciowych REST
, jak i GraphQL
, oraz jest niezależne od frameworka.
Mock Service Worker (MSW) działa poprzez przechwytywanie żądań wysyłanych przez Twoje testy, co pozwala na jego użycie bez zmiany kodu aplikacji. W przeglądarce używa Service Worker API. W Node.js i dla Vitest, używa biblioteki @mswjs/interceptors
. Aby dowiedzieć się więcej o MSW, przeczytaj ich wprowadzenie
Konfiguracja
Możesz użyć go w swoim pliku setup w następujący sposób:
import { afterAll, afterEach, beforeAll } from 'vitest';
import { setupServer } from 'msw/node';
import { graphql, 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 graphqlHandlers = [
graphql.query('ListPosts', () => {
return HttpResponse.json({
data: { posts },
});
}),
];
const server = setupServer(...restHandlers, ...graphqlHandlers);
// Uruchom serwer przed wszystkimi testami
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
// Zamknij serwer po wszystkich testach
afterAll(() => server.close());
// Zresetuj handlery po każdym teście `ważne dla izolacji testów`
afterEach(() => server.resetHandlers());
Konfiguracja serwera z
onUnhandleRequest: 'error'
zapewnia, że błąd zostanie zgłoszony, gdy pojawi się żądanie, które nie ma odpowiadającej mu obsługi żądań.
Więcej
MSW ma znacznie więcej do zaoferowania. Możesz uzyskać dostęp do ciasteczek i parametrów zapytania, definiować mockowe odpowiedzi błędów i wiele więcej! Aby zobaczyć wszystko, co możesz zrobić z MSW, przeczytaj ich dokumentację.
Timery
Kiedy testujemy kod, który zawiera timeouty lub interwały, zamiast czekać na ich zakończenie lub przekroczenie limitu czasu, możemy przyspieszyć nasze testy, używając „fałszywych” timerów, które mockują wywołania setTimeout
i setInterval
.
Szczegółowy opis API znajdziesz w sekcji vi.useFakeTimers
API.
Przykład
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
function executeAfterTwoHours(func) {
setTimeout(func, 1000 * 60 * 60 * 2); // 2 godziny
}
function executeEveryMinute(func) {
setInterval(func, 1000 * 60); // 1 minuta
}
const mock = vi.fn(() => console.log('executed'));
describe('delayed execution', () => {
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);
// przesunięcie o 2ms nie wywoła funkcji
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);
});
});
Klasy
Całą klasę można zamockować jednym wywołaniem vi.fn
– ponieważ wszystkie klasy są również funkcjami, działa to od razu. Należy pamiętać, że obecnie Vitest nie obsługuje słowa kluczowego new
, więc new.target
jest zawsze undefined
w ciele funkcji.
class Dog {
name: string;
constructor(name: string) {
this.name = name;
}
static getType(): string {
return 'animal';
}
speak(): string {
return 'bark!';
}
isHungry() {}
feed() {}
}
Możemy odtworzyć tę klasę za pomocą funkcji ES5:
const Dog = vi.fn(function (name) {
this.name = name;
});
// zauważ, że metody statyczne są mockowane bezpośrednio na obiekcie funkcji,
// a nie na instancji klasy
Dog.getType = vi.fn(() => 'mocked animal');
// mockuj metody "speak" i "feed" na każdej instancji klasy
// wszystkie instancje `new Dog()` będą miały te szpiegi
Dog.prototype.speak = vi.fn(() => 'loud bark!');
Dog.prototype.feed = vi.fn();
KIEDY UŻYWAĆ?
Ogólnie rzecz biorąc, zdefiniowałbyś klasę w ten sposób wewnątrz fabryki modułów, jeśli klasa jest ponownie eksportowana z innego modułu:
import { Dog } from './dog.js';
vi.mock(import('./dog.js'), () => {
const Dog = vi.fn();
Dog.prototype.feed = vi.fn();
// ... inne mocki
return { Dog };
});
Ta metoda może być również użyta do przekazania instancji klasy do funkcji, która przyjmuje ten sam interfejs:
// ./src/feed.ts
function feed(dog: Dog) {
// ...
}
// ./tests/dog.test.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);
});
Teraz, gdy tworzymy nową instancję klasy Dog
, jej metoda speak
(oraz feed
) jest już zamockowana:
const dog = new Dog('Cooper');
dog.speak(); // głośne szczekanie!
// możesz użyć wbudowanych asercji, aby sprawdzić poprawność wywołania
expect(dog.speak).toHaveBeenCalled();
Możemy ponownie przypisać wartość zwracaną dla konkretnej instancji:
const dog = new Dog('Cooper');
// "vi.mocked" to pomocnik typów, ponieważ
// TypeScript nie wie, że Dog to zamockowana klasa,
// opakowuje każdą funkcję w typ MockInstance<T>
// nie sprawdzając, czy funkcja jest mockiem
vi.mocked(dog.speak).mockReturnValue('hau hau');
dog.speak(); // hau hau
Aby zamockować właściwość, możemy użyć metody vi.spyOn(dog, 'name', 'get')
. Umożliwia to użycie asercji dla szpiega na zamockowanej właściwości:
const dog = new Dog('Cooper');
const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max');
expect(dog.name).toBe('Max');
expect(nameSpy).toHaveBeenCalledTimes(1);
TIP
Możesz również szpiegować gettery i settery, korzystając z tej samej metody.
Ściągawka
INFO
vi
w poniższych przykładach importuje się bezpośrednio z vitest
. Możesz również używać go globalnie, jeśli ustawisz globals
na true
w swojej konfiguracji.
Potrzebuję…
Mockować eksportowane zmienne
// some-path.js
export const getter = 'variable';
// some-path.test.ts
import * as exports from './some-path.js';
vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');
Mockować eksportowaną funkcję
- Przykład z
vi.mock
:
WARNING
Nie zapominaj, że wywołanie vi.mock
jest podnoszone na początek pliku. Zawsze zostanie wykonane przed wszystkimi importami.
// ./some-path.js
export function method() {}
import { method } from './some-path.js';
vi.mock('./some-path.js', () => ({
method: vi.fn(),
}));
- Przykład z
vi.spyOn
:
import * as exports from './some-path.js';
vi.spyOn(exports, 'method').mockImplementation(() => {});
Mockować implementację eksportowanej klasy
- Przykład z
vi.mock
i.prototype
:
// ./some-path.ts
export class SomeClass {}
import { SomeClass } from './some-path.js';
vi.mock(import('./some-path.js'), () => {
const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();
return { SomeClass };
});
// SomeClass.mock.instances będzie zawierać instancje SomeClass
- Przykład z
vi.spyOn
:
import * as mod from './some-path.js';
const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();
vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass);
Szpiegować obiekt zwrócony z funkcji
- Przykład użycia cache:
// some-path.ts
export function useObject() {
return { method: () => true };
}
// useObject.js
import { useObject } from './some-path.js';
const obj = useObject();
obj.method();
// useObject.test.js
import { useObject } from './some-path.js';
vi.mock(import('./some-path.js'), () => {
let _cache;
const useObject = () => {
if (!_cache) {
_cache = {
method: vi.fn(),
};
}
// teraz za każdym razem, gdy wywoływane jest useObject(),
// zwróci to samo odwołanie do obiektu
return _cache;
};
return { useObject };
});
const obj = useObject();
// obj.method zostało wywołane w module some-path
expect(obj.method).toHaveBeenCalled();
Mockować część modułu
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(); // ma oryginalne zachowanie
mocked(); // jest funkcją szpiegującą
WARNING
Nie zapominaj, że to mockuje jedynie dostęp zewnętrzny. W tym przykładzie, jeśli original
wywołuje mocked
wewnętrznie, zawsze wywoła funkcję zdefiniowaną w module, a nie w fabryce mocków.
Mockować bieżącą datę
Aby zamockować czas Date
, możesz użyć funkcji pomocniczej vi.setSystemTime
. Ta wartość nie zostanie automatycznie zresetowana między kolejnymi testami.
Pamiętaj, że użycie vi.useFakeTimers
również zmienia czas Date
.
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// zresetuj zamockowany czas
vi.useRealTimers();
Mockować zmienną globalną
Możesz ustawić zmienną globalną, przypisując wartość do globalThis
lub używając pomocnika vi.stubGlobal
. Podczas używania vi.stubGlobal
, wartość nie zostanie automatycznie zresetowana między kolejnymi testami, chyba że włączysz opcję konfiguracyjną unstubGlobals
lub wywołasz vi.unstubAllGlobals
.
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');
Mockować import.meta.env
- Aby zmienić zmienną środowiskową, możesz po prostu przypisać jej nową wartość.
WARNING
Wartość zmiennej środowiskowej nie zostanie automatycznie zresetowana między kolejnymi testami.
import { beforeEach, expect, it } from 'vitest';
// przed uruchomieniem testów "VITE_ENV" ma wartość "test"
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');
});
- Jeśli chcesz automatycznie zresetować wartość(i), możesz użyć pomocnika
vi.stubEnv
z włączoną opcją konfiguracyjnąunstubEnvs
(lub ręcznie wywołaćvi.unstubAllEnvs
w hookubeforeEach
):
import { expect, it, vi } from 'vitest';
// przed uruchomieniem testów "VITE_ENV" ma wartość "test"
import.meta.env.VITE_ENV === 'test';
it('changes value', () => {
vi.stubEnv('VITE_ENV', 'staging');
expect(import.meta.env.VITE_ENV).toBe('staging');
});
it('the value is restored before running an other test', () => {
expect(import.meta.env.VITE_ENV).toBe('test');
});
// vitest.config.ts
export default defineConfig({
test: {
unstubEnvs: true,
},
});