Mocking
Ao escrever testes, é comum precisar criar uma versão "falsa" de um serviço interno ou externo. Isso é geralmente chamado de mocking. O Vitest oferece funções utilitárias para auxiliar nesse processo, através do seu helper vi
. Você pode importá-lo de vitest
ou acessá-lo globalmente, caso a configuração global
esteja habilitada.
WARNING
Lembre-se sempre de limpar ou restaurar os mocks antes ou depois de cada execução de teste para reverter as alterações de estado do mock entre as execuções! Consulte a documentação de mockReset
para mais informações.
Se você não estiver familiarizado com os métodos vi.fn
, vi.mock
ou vi.spyOn
, consulte primeiro a seção da API.
Datas
Às vezes, é necessário ter controle sobre a data para garantir a consistência nos testes. O Vitest utiliza o pacote @sinonjs/fake-timers
para manipular temporizadores e a data do sistema. Você pode encontrar mais detalhes sobre a API específica neste link.
Exemplo
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(() => {
// informa ao Vitest que estamos usando tempo mockado
vi.useFakeTimers();
});
afterEach(() => {
// restaurando a data original após cada execução de teste
vi.useRealTimers();
});
it('allows purchases within business hours', () => {
// define a hora dentro do horário comercial
const date = new Date(2000, 1, 1, 13);
vi.setSystemTime(date);
// acessar Date.now() resultará na data definida acima
expect(purchase()).toEqual({ message: 'Success' });
});
it('disallows purchases outside of business hours', () => {
// define a hora fora do horário comercial
const date = new Date(2000, 1, 1, 19);
vi.setSystemTime(date);
// acessar Date.now() resultará na data definida acima
expect(purchase()).toEqual({ message: 'Error' });
});
});
Funções
O mocking de funções pode ser dividido em duas categorias diferentes: spying e mocking.
Às vezes, tudo o que você precisa é validar se uma função específica foi chamada (e, se for o caso, quais argumentos foram passados). Nesses casos, um spy seria tudo o que precisamos, e você pode usá-lo diretamente com vi.spyOn()
(leia mais aqui).
No entanto, os spies só podem ajudá-lo a monitorar funções; eles não são capazes de alterar a implementação dessas funções. Quando precisamos criar uma versão falsa (ou mockada) de uma função, podemos usar vi.fn()
(leia mais aqui).
Utilizamos Tinyspy como base para o mocking de funções, mas temos nosso próprio wrapper para torná-lo compatível com o jest
. Tanto vi.fn()
quanto vi.spyOn()
compartilham os mesmos métodos; no entanto, apenas o valor retornado por vi.fn()
pode ser chamado.
Exemplo
import { afterEach, describe, expect, it, vi } from 'vitest';
const messages = {
items: [
{ message: 'Simple test message', from: 'Testman' },
// ...
],
getLatest, // também pode ser um `getter` ou `setter`, se suportado
};
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);
});
});
Mais
Globais
Você pode simular variáveis globais que não estão disponíveis em ambientes jsdom
ou node
usando o helper vi.stubGlobal
. Ele atribuirá o valor da variável global ao objeto 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);
// agora você pode acessá-lo como `IntersectionObserver` ou `window.IntersectionObserver`
Módulos
Módulos mock permitem que você intercepte bibliotecas de terceiros que são invocadas em outro código, possibilitando testar argumentos, saídas ou até mesmo redeclarar sua implementação.
Consulte a seção da API vi.mock()
para uma descrição mais detalhada.
Algoritmo de Automocking
Se o seu código importar um módulo mockado, sem um arquivo __mocks__
associado ou uma factory
para esse módulo, o Vitest simulará o próprio módulo, invocando-o e simulando todas as suas exportações.
Os seguintes princípios se aplicam:
- Todos os arrays serão limpos
- Todos os valores primitivos e coleções permanecerão inalterados
- Todos os objetos serão clonados em profundidade
- Todas as instâncias de classes e seus protótipos serão clonados em profundidade
Módulos Virtuais
O Vitest suporta o mocking de módulos virtuais do Vite. Ele funciona de maneira diferente de como os módulos virtuais são tratados no Jest. Em vez de passar virtual: true
para uma função vi.mock
, você deve informar ao Vite que o módulo existe; caso contrário, ele falhará durante a análise. Você pode fazer isso de diversas maneiras:
- Forneça um alias:
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
test: {
alias: {
'$app/forms': resolve('./mocks/forms.js'),
},
},
});
- Forneça um plugin que resolva um módulo virtual:
import { defineConfig } from 'vitest/config';
export default defineConfig({
plugins: [
{
name: 'virtual-modules',
resolveId(id) {
if (id === '$app/forms') {
return 'virtual:$app/forms';
}
},
},
],
});
A vantagem da segunda abordagem é que você pode criar dinamicamente diferentes pontos de entrada virtuais. Se você redirecionar vários módulos virtuais para um único arquivo, todos eles serão afetados por vi.mock
; portanto, certifique-se de usar identificadores únicos.
Armadilhas do Mocking
Tenha em mente que não é possível simular chamadas para métodos que são invocados dentro de outros métodos do mesmo arquivo. Por exemplo, considere o seguinte código:
export function foo() {
return 'foo';
}
export function foobar() {
return `${foo()}bar`;
}
Não é possível simular o método foo
externamente, pois ele é referenciado diretamente. Assim, este código não terá efeito na chamada de foo
dentro de foobar
(mas afetará a chamada de foo
em outros módulos):
import { vi } from 'vitest';
import * as mod from './foobar.js';
// isso só afetará "foo" fora do módulo original
vi.spyOn(mod, 'foo');
vi.mock('./foobar.js', async importOriginal => {
return {
...(await importOriginal<typeof import('./foobar.js')>()),
// isso só afetará "foo" fora do módulo original
foo: () => 'mocked',
};
});
Você pode confirmar esse comportamento ao fornecer a implementação do método foobar
diretamente:
import * as mod from './foobar.js';
vi.spyOn(mod, 'foo');
// foo exportado referencia método mockado
mod.foobar(mod.foo);
export function foo() {
return 'foo';
}
export function foobar(injectedFoo) {
return injectedFoo === foo; // false
}
Esse é o comportamento esperado. Normalmente, é um sinal de código mal estruturado quando o mocking é utilizado dessa forma. Considere refatorar seu código em múltiplos arquivos ou melhorar a arquitetura de sua aplicação utilizando técnicas como injeção de dependência.
Exemplo
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { Client } from 'pg';
import { failure, success } from './handlers.js';
// obter tarefas
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) retornado(s)`,
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) retornado(s)',
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 });
});
});
Sistema de Arquivos
A simulação do sistema de arquivos garante que os testes não dependam do sistema de arquivos real, tornando-os mais confiáveis e previsíveis. Esse isolamento ajuda a evitar efeitos colaterais de testes anteriores. Isso permite testar condições de erro e casos extremos que podem ser difíceis ou impossíveis de replicar com um sistema de arquivos real, como problemas de permissão, cenários de disco cheio ou erros de leitura/gravação.
O Vitest não fornece nenhuma API de simulação de sistema de arquivos nativamente. Você pode usar vi.mock
para simular o módulo fs
manualmente, mas isso é difícil de manter. Em vez disso, recomendamos usar memfs
para essa finalidade. O memfs
cria um sistema de arquivos em memória, simulando operações de sistema de arquivos sem acessar o disco real. Essa abordagem é rápida e segura, evitando potenciais efeitos colaterais no sistema de arquivos real.
Exemplo
Para redirecionar automaticamente todas as chamadas fs
para memfs
, você pode criar os arquivos __mocks__/fs.cjs
e __mocks__/fs/promises.cjs
na raiz do seu projeto:
// também podemos usar `import`, mas, nesse caso,
// cada exportação deve ser explicitamente definida
const { fs } = require('memfs');
module.exports = fs;
// também podemos usar `import`, mas, nesse caso,
// cada exportação deve ser explicitamente definida
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';
// informa ao Vitest para usar a simulação de fs da pasta __mocks__
// isso pode ser feito em um arquivo de configuração se o fs precisar ser sempre mockado
vi.mock('node:fs');
vi.mock('node:fs/promises');
beforeEach(() => {
// reinicia o estado do fs em memória
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', () => {
// você pode usar vol.fromJSON para definir vários arquivos
vol.fromJSON(
{
'./dir1/hw.txt': 'hello dir1',
'./dir2/hw.txt': 'hello dir2',
},
// cwd padrão
'/tmp'
);
expect(readHelloWorld('/tmp/dir1/hw.txt')).toBe('hello dir1');
expect(readHelloWorld('/tmp/dir2/hw.txt')).toBe('hello dir2');
});
Requisições
Como o Vitest é executado no Node, simular requisições de rede é complicado; as APIs da web não estão disponíveis, então precisamos de algo que imite o comportamento da rede. Recomendamos o Mock Service Worker para isso. Ele permite simular requisições de rede http
, WebSocket
e GraphQL
, sendo independente de frameworks.
O Mock Service Worker (MSW) funciona interceptando as requisições feitas pelos seus testes, permitindo que você o use sem alterar nenhum código da sua aplicação. No navegador, ele utiliza a API Service Worker. No Node.js, e para o Vitest, ele utiliza a biblioteca @mswjs/interceptors
. Para saber mais sobre o MSW, consulte a introdução deles.
Configuração
Você pode utilizá-lo conforme o exemplo abaixo em seu arquivo de configuração:
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);
// Iniciar o servidor antes da execução de todos os testes
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
// Fechar o servidor após a execução de todos os testes
afterAll(() => server.close());
// Reiniciar os handlers após cada teste para garantir o isolamento dos testes
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);
// Iniciar o servidor antes da execução de todos os testes
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
// Fechar o servidor após a execução de todos os testes
afterAll(() => server.close());
// Reiniciar os handlers após cada teste para garantir o isolamento dos testes
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('Received message from client:', event.data);
// Ecoa a mensagem recebida de volta para o cliente
client.send(`Server received: ${event.data}`);
});
}),
];
const server = setupServer(...wsHandlers);
// Iniciar o servidor antes da execução de todos os testes
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
// Fechar o servidor após a execução de todos os testes
afterAll(() => server.close());
// Reiniciar os handlers após cada teste para garantir o isolamento dos testes
afterEach(() => server.resetHandlers());
Configurar o servidor com
onUnhandledRequest: 'error'
garante que um erro seja lançado sempre que houver uma requisição sem um handler correspondente.
Mais
O MSW oferece muito mais recursos. Você pode acessar cookies e parâmetros de consulta, definir respostas de erro simuladas, entre outras funcionalidades! Para descobrir tudo o que você pode fazer com o MSW, consulte a documentação.
Temporizadores
Ao testarmos código que envolve timeouts ou intervalos, em vez de fazer nossos testes esperarem ou expirarem, podemos acelerar os testes utilizando temporizadores "falsos" que simulam as chamadas para setTimeout
e setInterval
.
Consulte a seção da API vi.useFakeTimers
para uma descrição mais detalhada.
Exemplo
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
function executeAfterTwoHours(func) {
setTimeout(func, 1000 * 60 * 60 * 2); // 2 horas
}
function executeEveryMinute(func) {
setInterval(func, 1000 * 60); // 1 minuto
}
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);
// avançar por 2ms não irá disparar a função
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);
});
});
Classes
Você pode simular uma classe inteira com uma única chamada a vi.fn
— como todas as classes também são funções, isso funciona imediatamente. Atenção: atualmente o Vitest não respeita a palavra-chave new
, portanto new.target
é sempre undefined
no corpo de uma função.
class Dog {
name: string;
constructor(name: string) {
this.name = name;
}
static getType(): string {
return 'animal';
}
greet = (): string => {
return `Hi! My name is ${this.name}!`;
};
speak(): string {
return 'bark!';
}
isHungry() {}
feed() {}
}
Podemos reescrever esta classe utilizando funções ES5:
const Dog = vi.fn(function (name) {
this.name = name;
// simula os métodos de instância no construtor; cada instância terá seu próprio spy
this.greet = vi.fn(() => `Hi! My name is ${this.name}!`);
});
// observe que os métodos estáticos são simulados diretamente na função,
// e não na instância da classe
Dog.getType = vi.fn(() => 'mocked animal');
// simula os métodos "speak" e "feed" para cada instância de uma classe
// todas as instâncias de `new Dog()` herdarão e compartilharão esses spies
Dog.prototype.speak = vi.fn(() => 'loud bark!');
Dog.prototype.feed = vi.fn();
WARNING
Se um valor não primitivo for retornado da função construtora, esse valor se tornará o resultado da expressão new
. Nesse caso, o [[Prototype]]
pode não ser associado corretamente:
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 USAR?
Geralmente, você recriaria uma classe dessa forma dentro da fábrica de módulos se a classe for reexportada de outro módulo:
import { Dog } from './dog.js';
vi.mock(import('./dog.js'), () => {
const Dog = vi.fn();
Dog.prototype.feed = vi.fn();
// ... outros mocks
return { Dog };
});
Esse método também pode ser utilizado para passar uma instância de uma classe para uma função que espera a mesma interface:
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);
});
Agora, ao criarmos uma nova instância da classe Dog
, seu método speak
(assim como feed
e greet
) já está simulado:
const Cooper = new Dog('Cooper');
Cooper.speak(); // loud bark!
Cooper.greet(); // Hi! My name is Cooper!
// você pode utilizar asserções embutidas para verificar se a chamada foi feita corretamente
expect(Cooper.speak).toHaveBeenCalled();
expect(Cooper.greet).toHaveBeenCalled();
const Max = new Dog('Max');
// os métodos atribuídos ao protótipo são compartilhados entre as instâncias
expect(Max.speak).toHaveBeenCalled();
expect(Max.greet).not.toHaveBeenCalled();
Podemos reatribuir o valor de retorno de uma instância específica:
const dog = new Dog('Cooper');
// "vi.mocked" é um helper de tipo, pois o TypeScript não reconhece que Dog é uma classe simulada.
// Ele envolve qualquer função em um tipo MockInstance<T> sem validar se a função é um mock
vi.mocked(dog.speak).mockReturnValue('woof woof');
dog.speak(); // woof woof
Para simular uma propriedade, podemos utilizar o método vi.spyOn(dog, 'name', 'get')
. Isso possibilita o uso de asserções de spy na propriedade simulada:
const dog = new Dog('Cooper');
const nameSpy = vi.spyOn(dog, 'name', 'get').mockReturnValue('Max');
expect(dog.name).toBe('Max');
expect(nameSpy).toHaveBeenCalledTimes(1);
TIP
Você também pode monitorar getters e setters utilizando o mesmo método.
Folha de Dicas
INFO
vi
nos exemplos a seguir é importado diretamente de vitest
. Você também pode utilizá-lo globalmente, caso defina globals
como true
em sua configuração.
Eu gostaria de…
Simular variáveis exportadas:
export const getter = 'variable';
import * as exports from './example.js';
vi.spyOn(exports, 'getter', 'get').mockReturnValue('mocked');
Simular uma função exportada:
- Exemplo com
vi.mock
:
WARNING
Não se esqueça que uma chamada vi.mock
é movida para o topo do arquivo. Ela sempre será executada antes de todas as importações.
export function method() {}
import { method } from './example.js';
vi.mock('./example.js', () => ({
method: vi.fn(),
}));
- Exemplo com
vi.spyOn
:
import * as exports from './example.js';
vi.spyOn(exports, 'method').mockImplementation(() => {});
Simular uma implementação de classe exportada:
- Exemplo com
vi.mock
e.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 conterá instâncias de SomeClass
- Exemplo com
vi.spyOn
:
import * as mod from './example.js';
const SomeClass = vi.fn();
SomeClass.prototype.someMethod = vi.fn();
vi.spyOn(mod, 'SomeClass').mockImplementation(SomeClass);
Espionar um objeto retornado por uma função:
- Exemplo com uso de 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(),
};
}
// agora, sempre que useObject() for chamado, ele
// retornará a mesma referência de objeto
return _cache;
};
return { useObject };
});
const obj = useObject();
// obj.method foi chamado dentro de some-path
expect(obj.method).toHaveBeenCalled();
Simular parte de um módulo:
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(); // tem comportamento original
mocked(); // é uma função spy
WARNING
Não se esqueça que isso apenas simula o acesso externo. Neste exemplo, se original
chamar mocked
internamente, ele sempre chamará a função definida no módulo original, e não a da fábrica de mocks.
Simular a data atual:
Para simular a hora de Date
, você pode usar a função auxiliar vi.setSystemTime
. Este valor não será redefinido automaticamente entre os testes.
Tenha em mente que usar vi.useFakeTimers
também altera a hora de Date
.
const mockDate = new Date(2022, 0, 1);
vi.setSystemTime(mockDate);
const now = new Date();
expect(now.valueOf()).toBe(mockDate.valueOf());
// reinicia o tempo simulado
vi.useRealTimers();
Simular uma variável global:
Você pode definir uma variável global atribuindo um valor a globalThis
ou usando o helper vi.stubGlobal
. Ao usar vi.stubGlobal
, ela não será redefinida automaticamente entre os testes, a menos que você habilite a opção de configuração unstubGlobals
ou chame vi.unstubAllGlobals
.
vi.stubGlobal('__VERSION__', '1.0.0');
expect(__VERSION__).toBe('1.0.0');
Simular import.meta.env
:
- Para alterar uma variável de ambiente, você pode simplesmente atribuir um novo valor a ela:
WARNING
O valor da variável de ambiente não será redefinido automaticamente entre os testes.
import { beforeEach, expect, it } from 'vitest';
// antes de executar os testes, "VITE_ENV" é "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');
});
- Se você quiser redefinir automaticamente os valores, pode usar o auxiliar
vi.stubEnv
com a opção de configuraçãounstubEnvs
habilitada (ou chamarvi.unstubAllEnvs
manualmente em um hookbeforeEach
):
import { expect, it, vi } from 'vitest';
// antes de executar os testes, "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('the value is restored before running an other test', () => {
expect(import.meta.env.VITE_ENV).toBe('test');
});
export default defineConfig({
test: {
unstubEnvs: true,
},
});