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); // false
Padrõ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(); // fake
Você 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
none
foi renomeado parapreview
#5842 - O provedor
preview
agora é o padrão #5842 indexScripts
foi renomeado paraorchestratorScripts
#5842
Opções Obsoletas Removidas
Algumas opções obsoletas foram removidas:
- Comando
vitest typecheck
- usevitest --typecheck
em vez disso - Variáveis de ambiente
VITEST_JUNIT_CLASSNAME
eVITEST_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
SnapshotEnvironment
devitest
- importe-o devitest/snapshot
em 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
SnapshotClient
apenas para sobrescrever o métodoequalityCheck
: basta passá-lo comoisEqual
ao iniciar uma instância client.setTest
foi renomeado paraclient.startCurrentRun
client.resetCurrent
foi 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.
--threads
agora é--pool=threads
--no-threads
agora é--pool=forks
--single-thread
agora é--poolOptions.threads.singleThread
--experimental-vm-threads
agora é--pool=vmThreads
--experimental-vm-worker-memory-limit
agora é--poolOptions.vmThreads.memoryLimit
--isolate
agora é--poolOptions.<pool-name>.isolate
ebrowser.isolate
test.maxThreads
agora étest.poolOptions.<pool-name>.maxThreads
test.minThreads
agora étest.poolOptions.<pool-name>.minThreads
test.useAtomics
agora étest.poolOptions.<pool-name>.useAtomics
test.poolMatchGlobs.child_process
agora étest.poolMatchGlobs.forks
test.poolMatchGlobs.experimentalVmThreads
agora é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.