Skip to content
Vitest 3
Main Navigation Guia & APIConfiguraçãoModo NavegadorAPI Avançada
3.2.0
2.1.9
1.6.1
0.34.6

Português – Brasil

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

Português – Brasil

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

Aparência

Sidebar Navigation

Introdução

Por que Vitest

Primeiros Passos

Recursos

Configurando o Vitest

API

Referência da API de Teste

Funções Mock

Vi

expect

expectTypeOf

assert

assertType

Guia

Interface de Linha de Comando

Filtragem de Testes

Projetos de Teste

Reporters

Cobertura

Snapshot

Mocking

Paralelismo

Testando Tipos

Vitest UI

Testes no Código-Fonte

Contexto de Testes

Anotações em Testes

Ambiente de Teste

Estendendo Matchers

Integrações com IDEs

Depuração

Erros Comuns

Guia de Migração

Migrando para o Vitest 3.0

Migrando do Jest

Desempenho

Análise de Desempenho de Testes

Melhorando o Desempenho

Modo Navegador

APIs Avançadas

Comparações com Outros Test Runners

Nesta página

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 ​

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(() => {
    // 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 ​

js
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 ​

  • Funções Mock do Jest

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.

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

// 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:

  1. Forneça um alias:
ts
import { defineConfig } from 'vitest/config';
import { resolve } from 'node:path';
export default defineConfig({
  test: {
    alias: {
      '$app/forms': resolve('./mocks/forms.js'),
    },
  },
});
  1. Forneça um plugin que resolva um módulo virtual:
ts
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:

ts
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):

ts
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:

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

vi.spyOn(mod, 'foo');

// foo exportado referencia método mockado
mod.foobar(mod.foo);
ts
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 ​

js
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:

ts
// também podemos usar `import`, mas, nesse caso,
// cada exportação deve ser explicitamente definida

const { fs } = require('memfs');
module.exports = fs;
ts
// também podemos usar `import`, mas, nesse caso,
// cada exportação deve ser explicitamente definida

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

// 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:

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

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

// 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());
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('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 ​

js
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.

ts
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:

ts
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:

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

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

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

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

QUANDO USAR?

Geralmente, você recriaria uma classe dessa forma dentro da fábrica de módulos se a classe for reexportada de outro módulo:

ts
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:

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

Agora, ao criarmos uma nova instância da classe Dog, seu método speak (assim como feed e greet) já está simulado:

ts
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:

ts
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:

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

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: ​

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

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

Simular uma função exportada: ​

  1. 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.

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

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

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

Simular uma implementação de classe exportada: ​

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

vi.mock(import('./example.js'), () => {
  const SomeClass = vi.fn();
  SomeClass.prototype.someMethod = vi.fn();
  return { SomeClass };
});
// SomeClass.mock.instances conterá instâncias de SomeClass
  1. Exemplo com vi.spyOn:
ts
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: ​

  1. Exemplo com uso de 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(),
      };
    }
    // 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: ​

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(); // 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.

ts
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.

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

Simular import.meta.env: ​

  1. 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.

ts
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');
});
  1. Se você quiser redefinir automaticamente os valores, pode usar o auxiliar vi.stubEnv com a opção de configuração unstubEnvs habilitada (ou chamar vi.unstubAllEnvs manualmente em um hook beforeEach):
ts
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');
});
ts
export default defineConfig({
  test: {
    unstubEnvs: true,
  },
});
Pager
AnteriorSnapshot
PróximoParalelismo

Distribuído sob a Licença MIT.

Copyright (c) 2021-Present Vitest Team

https://vitest.dev/guide/mocking

Distribuído sob a Licença MIT.

Copyright (c) 2021-Present Vitest Team