Guia de Migração
Migrando para o Vitest 3.0
Opções de Teste como Terceiro Argumento
O Vitest 3.0 emitirá um aviso se você passar um objeto como terceiro argumento para as funções test ou describe:
test('validation works', () => {
// ...
}, { retry: 3 });
test('validation works', { retry: 3 }, () => {
// ...
});A próxima versão principal lançará um erro se o terceiro argumento for um objeto. Observe que o número de timeout não está obsoleto:
test('validation works', () => {
// ...
}, 1000); // Ok ✅browser.name e browser.providerOptions estão Obsoletos
Ambos browser.name e browser.providerOptions serão removidos no Vitest 4. Em vez deles, use a nova opção browser.instances:
export default defineConfig({
test: {
browser: {
name: 'chromium',
providerOptions: {
launch: { devtools: true },
},
instances: [
{
browser: 'chromium',
launch: { devtools: true },
},
],
},
},
})Com o novo campo browser.instances, você também pode especificar várias configurações de navegador.
spy.mockReset Agora Restaura a Implementação Original
Não havia uma boa maneira de redefinir o spy para a implementação original sem reaplicar o mesmo. Agora, spy.mockReset redefinirá a função de implementação para a original em vez de uma função noop.
const foo = {
bar: () => 'Hello, world!',
};
vi.spyOn(foo, 'bar').mockImplementation(() => 'Hello, mock!');
foo.bar(); // 'Hello, mock!'
foo.bar.mockReset();
foo.bar(); // undefined
foo.bar(); // 'Hello, world!'vi.spyOn Reutiliza Mock se o Método Já Estiver Mockado
Anteriormente, o Vitest sempre atribuía um novo spy ao monitorar um objeto. Isso causava erros com mockRestore porque ele restauraria o spy para o spy anterior em vez da função original:
vi.spyOn(fooService, 'foo').mockImplementation(() => 'bar');
vi.spyOn(fooService, 'foo').mockImplementation(() => 'bar');
vi.restoreAllMocks();
vi.isMockFunction(fooService.foo); // true
vi.isMockFunction(fooService.foo); // falsePadrões de Timers Falsos
O Vitest não fornece mais opções padrão para fakeTimers.toFake. Agora, o Vitest irá mockar qualquer API relacionada a timers se estiver disponível (exceto nextTick). Por exemplo, performance.now() agora é mockado quando vi.useFakeTimers é chamado.
vi.useFakeTimers();
performance.now(); // original
performance.now(); // fakeVocê pode reverter para o comportamento anterior especificando os timers ao chamar vi.useFakeTimers ou globalmente na configuração:
export default defineConfig({
test: {
fakeTimers: {
toFake: [
'setTimeout',
'clearTimeout',
'setInterval',
'clearInterval',
'setImmediate',
'clearImmediate',
'Date',
]
},
},
})Igualdade de Erro Mais Estrita
O Vitest agora verifica mais propriedades quando compara erros usando toEqual ou toThrowError. O Vitest agora compara name, message, cause e AggregateError.errors. Para Error.cause, a comparação é feita de forma assimétrica:
expect(new Error('hi', { cause: 'x' })).toEqual(new Error('hi')); // ✅
expect(new Error('hi')).toEqual(new Error('hi', { cause: 'x' })); // ❌Além da verificação de mais propriedades, o Vitest agora compara protótipos de erro. Por exemplo, se TypeError foi lançado, a verificação de igualdade deve referenciar TypeError, não Error:
expect(() => {
throw new TypeError('type error');
})
.toThrowError(new Error('type error'))
.toThrowError(new TypeError('type error')); Veja o PR para mais detalhes: #5876.
A exportação da condição module não é resolvida por padrão no Vite 6
O Vite 6 permite opções resolve.conditions mais flexíveis, e o Vitest as configura para excluir a exportação condicional module por padrão. Veja também o guia de migração do Vite 6 para detalhes das mudanças do lado do Vite.
O Tipo Custom Está Obsoleto API
O tipo Custom agora é um sinônimo para o tipo Test. Observe que o Vitest atualizou os tipos públicos na versão 2.1 e renomeou as exportações para RunnerCustomCase e RunnerTestCase:
import {
RunnerCustomCase,
RunnerTestCase,
} from 'vitest';Se você estiver usando getCurrentSuite().custom(), o type da tarefa retornada agora é igual a 'test'. O tipo Custom será removido no Vitest 4.
O Tipo WorkspaceSpec Não é Mais Utilizado API
Na API pública, este tipo era utilizado em sequenciadores personalizados. Por favor, migre para TestSpecification em vez disso.
onTestFinished e onTestFailed Agora Recebem um Contexto
Os hooks onTestFinished e onTestFailed anteriormente recebiam um resultado de teste como primeiro argumento. Agora, eles recebem um contexto de teste, como beforeEach e afterEach.
Alterações na API de Snapshot API
A API pública de Snapshot em @vitest/snapshot foi alterada para suportar múltiplos estados dentro de uma única execução. Veja o PR para mais detalhes: #6817
Observe que essas alterações afetam apenas os desenvolvedores que usam a API de Snapshot diretamente. Não houve alterações na API .toMatchSnapshot.
Alterações na Assinatura do Tipo resolveConfig API
O resolveConfig agora é mais útil. Em vez de aceitar uma configuração Vite previamente resolvida, ele agora aceita uma configuração de usuário e retorna a configuração resolvida.
Esta função não é usada internamente e é exposta exclusivamente como uma API pública.
Tipos de vitest/reporters Limpos API
O ponto de entrada vitest/reporters agora exporta apenas as implementações de reporters e os tipos de opções. Se você precisar de acesso a TestCase/TestSuite e outros tipos relacionados a tarefas, importe-os adicionalmente de vitest/node.
A cobertura ignora arquivos de teste mesmo quando coverage.excludes é sobrescrito.
Não é mais possível incluir arquivos de teste no relatório de cobertura ao sobrescrever coverage.excludes. Os arquivos de teste agora são sempre excluídos.
Migrando para o Vitest 2.0
O Pool Padrão é forks
O Vitest 2.0 altera a configuração padrão para pool para 'forks' para melhor estabilidade. Você pode ler a motivação completa no PR.
Se você usou poolOptions sem especificar um pool, pode ser necessário atualizar a configuração:
export default defineConfig({
test: {
poolOptions: {
threads: {
singleThread: true,
},
forks: {
singleFork: true,
},
}
}
})Hooks Agora São Executados Sequencialmente
Antes do Vitest 2.0, todos os hooks eram executados em paralelo. No 2.0, todos os hooks são executados serialmente. Além disso, os hooks afterAll/afterEach são executados em ordem inversa.
Para reverter para a execução paralela de hooks, altere sequence.hooks para 'parallel':
export default defineConfig({
test: {
sequence: {
hooks: 'parallel',
},
},
})suite.concurrent Executa Todos os Testes Concorrentemente
Anteriormente, especificar concurrent em uma suíte agrupava testes concorrentes por suítes, executando-os sequencialmente. Agora, seguindo o comportamento do Jest, todos os testes são executados concorrentemente (sujeito aos limites de maxConcurrency).
coverage.ignoreEmptyLines do V8 Coverage Está Habilitado por Padrão
O valor padrão de coverage.ignoreEmptyLines agora é verdadeiro. Essa mudança significativa pode afetar os relatórios de cobertura de código, exigindo ajustes nos limites de cobertura para alguns projetos. Esse ajuste afeta apenas a configuração padrão quando coverage.provider é 'v8'.
Remoção da Opção watchExclude
O Vitest usa o watcher do Vite. Exclua arquivos ou diretórios adicionando-os a server.watch.ignored:
export default defineConfig({
server: {
watch: {
ignored: ['!node_modules/examplejs']
}
}
})--segfault-retry Removido
Com as mudanças no pool padrão, esta opção não é mais necessária. Se você tiver erros de segfault, tente mudar para o pool 'forks'. Se o problema persistir, por favor, abra uma nova issue com um exemplo de reprodução.
Tarefa Vazia em Tarefas de Suíte Removida
Esta é a mudança na API de tarefas avançada. Anteriormente, navegar por .suite eventualmente levaria à suíte interna vazia que era usada em vez de uma tarefa de arquivo.
Isso torna .suite opcional; se a tarefa for definida no nível superior, ela não terá uma suíte. Você pode usar a propriedade .file que agora está presente em todas as tarefas (incluindo a própria tarefa de arquivo, então tome cuidado para não cair em recursão infinita).
Essa mudança também remove o arquivo de expect.getState().currentTestName e torna expect.getState().testPath obrigatório.
task.meta é Adicionado ao JSON Reporter
O JSON reporter agora imprime task.meta para cada resultado de asserção.
Tipos Genéricos Simplificados de Funções Mock (ex: vi.fn<T>, Mock<T>)
Anteriormente, vi.fn<TArgs, TReturn> aceitava dois tipos genéricos separadamente para argumentos e valor de retorno. Isso foi simplificado para aceitar diretamente um tipo de função vi.fn<T> para simplificar o uso.
import { vi } from 'vitest';
import type { Mock } from 'vitest';
const add = (x: number, y: number): number => x + y;
// using vi.fn<T>
const mockAdd = vi.fn<Parameters<typeof add>, ReturnType<typeof add>>();
const mockAdd = vi.fn<typeof add>();
// using Mock<T>
const mockAdd: Mock<Parameters<typeof add>, ReturnType<typeof add>> = vi.fn();
const mockAdd: Mock<typeof add> = vi.fn(); Acessando mock.results Resolvidos
Anteriormente, o Vitest resolvia os valores de mock.results se a função retornasse uma Promise. Agora existe uma propriedade mock.settledResults separada que é preenchida somente quando a Promise retornada é resolvida ou rejeitada.
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
const result = fn.mock.results[0]; // 'result'
const result = fn.mock.results[0]; // 'Promise<result>'
const settledResult = fn.mock.settledResults[0]; // 'result'Com essa mudança, também introduzimos novos matchers toHaveResolved* semelhantes a toHaveReturned para facilitar a migração se você usava toHaveReturned antes:
const fn = vi.fn().mockResolvedValueOnce('result');
await fn();
expect(fn).toHaveReturned('result');
expect(fn).toHaveResolved('result'); Modo Navegador
O Modo Navegador do Vitest teve muitas mudanças durante o ciclo beta. Você pode ler sobre nossa filosofia no Modo Navegador na página de discussão do GitHub.
A maioria das mudanças foram aditivas, mas houve algumas pequenas mudanças que quebram a compatibilidade:
- O provedor
nonefoi renomeado parapreview#5842 - O provedor
previewagora é o padrão #5842 indexScriptsfoi renomeado paraorchestratorScripts#5842
Opções Obsoletas Removidas
Algumas opções obsoletas foram removidas:
- Comando
vitest typecheck- usevitest --typecheckem vez disso - Variáveis de ambiente
VITEST_JUNIT_CLASSNAMEeVITEST_JUNIT_SUITE_NAME(use opções de reporter em vez disso) - Verificação para cobertura
c8(use coverage-v8 em vez disso) - Exportação de
SnapshotEnvironmentdevitest- importe-o devitest/snapshotem vez disso SpyInstanceé removido em favor deMockInstance
Migrando para o Vitest 1.0
Requisitos Mínimos
O Vitest 1.0 requer Vite 5.0 e Node.js 18 ou superior.
Todos os subpacotes @vitest/* requerem a versão 1.0 do Vitest.
Atualização de Snapshots #3961
Aspas em snapshots não são mais escapadas, e todos os snapshots usam aspas de crase (`) mesmo que a string seja apenas uma única linha.
- Aspas não são mais escapadas:
expect({ foo: 'bar' }).toMatchInlineSnapshot(`
Object {
- \\"foo\\": \\"bar\\",
+ "foo": "bar",
}
`)- Snapshots de uma linha agora usam aspas "`" em vez de ':
- expect('some string').toMatchInlineSnapshot('"some string"')
+ expect('some string').toMatchInlineSnapshot(`"some string"`)Também houve mudanças no pacote @vitest/snapshot. Se você não o estiver usando diretamente, não precisa mudar nada.
- Você não precisa mais estender
SnapshotClientapenas para sobrescrever o métodoequalityCheck: basta passá-lo comoisEqualao iniciar uma instância client.setTestfoi renomeado paraclient.startCurrentRunclient.resetCurrentfoi renomeado paraclient.finishCurrentRun
Pools são Padronizados #4172
Removemos muitas opções de configuração para facilitar a configuração do runner às suas necessidades. Por favor, dê uma olhada nos exemplos de migração se você depende de --threads ou outras flags relacionadas.
--threadsagora é--pool=threads--no-threadsagora é--pool=forks--single-threadagora é--poolOptions.threads.singleThread--experimental-vm-threadsagora é--pool=vmThreads--experimental-vm-worker-memory-limitagora é--poolOptions.vmThreads.memoryLimit--isolateagora é--poolOptions.<pool-name>.isolateebrowser.isolatetest.maxThreadsagora étest.poolOptions.<pool-name>.maxThreadstest.minThreadsagora étest.poolOptions.<pool-name>.minThreadstest.useAtomicsagora étest.poolOptions.<pool-name>.useAtomicstest.poolMatchGlobs.child_processagora étest.poolMatchGlobs.forkstest.poolMatchGlobs.experimentalVmThreadsagora étest.poolMatchGlobs.vmThreads
{
scripts: {
- "test": "vitest --no-threads"
// Para comportamento idêntico:
+ "test": "vitest --pool forks --poolOptions.forks.singleFork"
// Ou múltiplos forks paralelos:
+ "test": "vitest --pool forks"
}
}{
scripts: {
- "test": "vitest --experimental-vm-threads"
+ "test": "vitest --pool vmThreads"
}
}{
scripts: {
- "test": "vitest --isolate false"
+ "test": "vitest --poolOptions.threads.isolate false"
}
}{
scripts: {
- "test": "vitest --no-threads --isolate false"
+ "test": "vitest --pool forks --poolOptions.forks.isolate false"
}
}Alterações na Cobertura #4265, #4442
A opção coverage.all agora está habilitada por padrão. Isso significa que todos os arquivos do projeto que correspondem ao padrão coverage.include serão processados, mesmo que não sejam executados.
A forma da API de limites de cobertura foi alterada, e agora suporta a especificação de limites para arquivos específicos usando padrões glob:
export default defineConfig({
test: {
coverage: {
- perFile: true,
- thresholdAutoUpdate: true,
- 100: true,
- lines: 100,
- functions: 100,
- branches: 100,
- statements: 100,
+ thresholds: {
+ perFile: true,
+ autoUpdate: true,
+ 100: true,
+ lines: 100,
+ functions: 100,
+ branches: 100,
+ statements: 100,
+ }
}
}
})Tipos de Mock #4400
Alguns tipos foram removidos em favor da nomenclatura "Mock" no estilo Jest.
- import { EnhancedSpy, SpyInstance } from 'vitest'
+ import { MockInstance } from 'vitest'WARNING
SpyInstance está obsoleto em favor de MockInstance e será removido na próxima versão principal.
Mocks de Timer #3925
vi.useFakeTimers() não mocka mais automaticamente process.nextTick. Ainda é possível mockar process.nextTick especificando-o explicitamente usando vi.useFakeTimers({ toFake: ['nextTick'] }).
No entanto, mockar process.nextTick não é possível ao usar --pool=forks. Use uma opção --pool diferente se precisar fazer o mock de process.nextTick.
Migrando do Jest
O Vitest foi projetado com uma API compatível com Jest, a fim de tornar a migração do Jest o mais simples possível. Apesar desses esforços, você ainda pode encontrar as seguintes diferenças:
Globais como Padrão
O Jest tem sua API de globais habilitada por padrão. O Vitest não. Você pode habilitar as globais através da configuração globals ou atualizar seu código para usar importações do módulo vitest.
Se você decidir manter as globais desabilitadas, esteja ciente de que bibliotecas comuns como testing-library não executarão a limpeza automática do DOM.
spy.mockReset
O mockReset do Jest substitui a implementação do mock por uma função que não faz nada e retorna undefined.
O mockReset do Vitest redefine a implementação do mock para a original. Ou seja, redefinir um mock criado por vi.fn(impl) redefinirá a implementação do mock para impl.
Mocks de Módulo
Ao mockar um módulo no Jest, o valor de retorno do argumento de fábrica é a exportação padrão. No Vitest, o argumento de fábrica deve retornar um objeto com cada exportação explicitamente definida. Por exemplo, o seguinte jest.mock teria que ser atualizado da seguinte forma:
jest.mock('./some-path', () => 'hello')
vi.mock('./some-path', () => ({
default: 'hello',
})) Para mais detalhes, consulte a seção da API vi.mock.
Comportamento de Auto-Mocking
Ao contrário do Jest, módulos mockados em <root>/__mocks__ não são carregados a menos que vi.mock() seja chamado. Se você precisar que eles sejam mockados em todos os testes, como no Jest, você pode mocká-los dentro de setupFiles.
Importando o Original de um Pacote Mockado
Se você estiver mockando apenas parcialmente um pacote, pode ter usado anteriormente a função requireActual do Jest. No Vitest, você deve substituir essas chamadas por vi.importActual.
const { cloneDeep } = jest.requireActual('lodash/cloneDeep');
const { cloneDeep } = await vi.importActual('lodash/cloneDeep'); Estende o mocking para bibliotecas externas
Ao contrário do Jest, que estende o mocking para bibliotecas externas por padrão, no Vitest, ao mockar um módulo e desejar que esse mock se estenda a outras bibliotecas externas que o utilizam, você deve especificar explicitamente qual biblioteca de terceiros deve ser mockada. Isso é feito incluindo a biblioteca externa no seu código-fonte através de server.deps.inline.
server.deps.inline: ["lib-name"]expect.getState().currentTestName
Os nomes de test do Vitest são unidos com um símbolo > para facilitar a distinção entre testes e suítes, enquanto o Jest usa um espaço vazio ().
- `${describeTitle} ${testTitle}`
+ `${describeTitle} > ${testTitle}`Envs
Assim como o Jest, o Vitest define NODE_ENV como test, caso não tenha sido definido anteriormente. O Vitest também tem uma contraparte para JEST_WORKER_ID chamada VITEST_POOL_ID (sempre menor ou igual a maxThreads), então, se você depende dela, não se esqueça de renomeá-la. O Vitest também expõe VITEST_WORKER_ID, que é um ID único de um worker em execução – este número não é afetado por maxThreads e aumentará a cada worker criado.
Substituir propriedade
No Jest, para modificar um objeto, você usaria a API replaceProperty. No Vitest, você pode alcançar o mesmo resultado usando vi.stubEnv ou vi.spyOn.
Callback Done
A partir do Vitest v0.10.0, o estilo de callback para declarar testes está obsoleto. Você pode reescrevê-los para usar funções async/await, ou usar Promises para simular o estilo de callback.
it('should work', (done) => {
it('should work', () => new Promise(done => {
// ...
done()
})
})) Hooks
Os hooks beforeAll/beforeEach podem retornar uma função de teardown no Vitest. Consequentemente, pode ser necessário reescrever suas declarações de hooks, caso retornem algo diferente de undefined ou null:
beforeEach(() => setActivePinia(createTestingPinia()))
beforeEach(() => { setActivePinia(createTestingPinia()) }) No Jest, os hooks são chamados sequencialmente (um após o outro). Por padrão, o Vitest executa os hooks em paralelo. Para usar o comportamento do Jest, atualize a opção sequence.hooks:
export default defineConfig({
test: {
sequence: {
hooks: 'list',
}
}
})Tipos
O Vitest não tem um equivalente ao namespace jest, então você precisará importar os tipos diretamente de vitest:
let fn: jest.Mock<(name: string) => number>;
import type { Mock } from 'vitest';
let fn: Mock<(name: string) => number>; Timers
O Vitest não suporta os timers legados do Jest.
Timeout
Se você usou jest.setTimeout, precisará migrar para vi.setConfig:
jest.setTimeout(5_000);
vi.setConfig({ testTimeout: 5_000 }); Vue Snapshots
Este não é um recurso específico do Jest, mas se você usava o Jest com o preset vue-cli, precisará instalar o pacote jest-serializer-vue e configurá-lo dentro de setupFiles:
import { defineConfig } from 'vite';
export default defineConfig({
test: {
setupFiles: ['./tests/unit/setup.js'],
},
});import vueSnapshotSerializer from 'jest-serializer-vue';
expect.addSnapshotSerializer(vueSnapshotSerializer);Caso contrário, seus snapshots terão muitas aspas duplas (") escapadas.