O que mudou no Vitest 5
Veja o que mudou no Vitest 5: ganhos de desempenho, alterações incompatíveis, novos padrões, caminhos de relatórios e etapas para atualizar testes e CI.
O Vitest 5.0, lançado em 3 de setembro de 2026, é uma versão major focada em desempenho. Ele exige Node.js 22.12.0+ e Vite 6.4.0+, ativa a limpeza de mocks por padrão, faz falhar asserções assíncronas sem await e move a saída dos reporters para um único diretório .vitest/.
A maioria das falhas após a atualização é fácil de resolver. As difíceis são os testes que passam localmente no Vitest 4 e ficam vermelhos no CI com um erro que não diz nada sobre a causa.
Este artigo organiza as notas de lançamento da v5.0.0 por impacto. Primeiro, o que realmente ficou mais rápido. Em seguida, as mudanças que exigem edições no código, as mudanças que alteram silenciosamente caminhos e regras de correspondência, um checklist de atualização e um veredito.
Principais pontos
- O Vitest 5.0 exige Node.js 22.12.0 ou posterior e Vite 6.4.0 ou posterior.
- Os benchmarks da equipe do Vitest mostram a maioria das configurações testadas rodando de 8 a 25% mais rápido, e até 53% mais rápido em algumas configurações com pools de VM. Configurações dominadas pela preparação do ambiente praticamente não mudam.
clearMocksagora temtruecomo padrão. Por isso, uma asserção sobre o histórico de chamadas registrado em um arquivo de setup, em um hookbeforeAllou em um teste anterior agora vê zero chamadas.- Relatórios blob, anexos e a saída dos reporters JSON, JUnit e HTML agora usam, por padrão, caminhos dentro de
.vitest/. As etapas de artefatos do CI precisam ser atualizadas. toThrow('')agora corresponde a qualquer erro lançado. Uma asserção que pretende verificar uma mensagem vazia precisa de um padrão explícito.
Por que o Vitest 5 é mais rápido?
A maioria das configurações nos benchmarks da própria equipe do Vitest roda de 8 a 25% mais rápido, segundo o anúncio do Vitest 5. Os pools de VM são os que mais ganham, com até 53% em algumas configurações. Nem toda configuração fica mais rápida. Execuções em que a criação do ambiente de teste consome a maior parte do tempo, como forks com jsdom e isolamento, ficam a menos de 3% do Vitest 4.1.
Os números vêm do vitest-dev/benchmarks, onde a equipe gerou aplicações de teste de diferentes tamanhos, desde um pacote pequeno de 5 arquivos até um monólito de 1.280 módulos. No post de lançamento da VoidZero, isso é arredondado para “pools de VM até 53% mais rápidos, ganho de ~18% em todos os cenários, incluindo o Browser Mode”.
Segundo as notas de lançamento, quatro mudanças produzem a maior parte do ganho:
- Servidor Vite compartilhado. Os projetos inline agora compartilham um único servidor Vite, em vez de cada um iniciar o seu.
fsModuleCache. Agora é uma opção de nível superior. Ela salva os módulos transformados em disco, de modo que uma nova execução ou outro processo do Vitest pode pular esse trabalho.- Menos idas e voltas. Módulos já transformados agora chegam a um worker em uma única viagem a partir do processo principal.
- Reutilização nos pools de VM. Os pools
vmThreadsevmForkscompartilham código compilado entre contextos e carregam o grafo de módulos antecipadamente.
O Vitest também oferece suporte ao cache de compilação em disco do Node, mas ele precisa ser ativado explicitamente.
Quais mudanças do Vitest 5 exigem edição no código?
Seis mudanças do Vitest 5 causam uma falha de teste ou um erro de configuração na primeira execução. O guia de migração aborda cada uma delas.
| Mudança | Sintoma na primeira execução | Correção |
|---|---|---|
clearMocks: true por padrão | Asserções de contagem de chamadas veem 0 | Dispare as chamadas dentro do teste que faz a asserção ou defina clearMocks: false |
Asserção assíncrona sem await | O teste falha | Adicione await |
Chamada vi içada fora do nível superior | Lança um erro | Mova-a para o escopo do módulo |
sequential removido | API removida | { concurrent: false } |
| Sem busca de config em diretórios pais | Config não encontrada | Adicione uma config na pasta do pacote |
| API de bench reescrita | Código de bench antigo quebra | Migre para o modelo de fixtures |
Limpeza de mocks e hoisting
No Vitest 5, clearMocks tem true como padrão, então vi.clearAllMocks() é executado antes de cada teste. O histórico de chamadas registrado em um arquivo de setup, em um hook beforeAll ou em um teste anterior é apagado antes que o próximo teste faça asserções sobre ele. As implementações dos mocks são mantidas.
// Vitest 5.0.x
const track = vi.fn()
beforeAll(() => initAnalytics(track))
it('tracks once on init', () => {
expect(track).toHaveBeenCalledTimes(1) // now receives 0 calls
})
A correção é disparar a chamada dentro do teste que faz a asserção sobre ela. Definir clearMocks: false na config test restaura o comportamento antigo enquanto você audita a suíte.
Chamar vi.mock, ou qualquer outra chamada vi içada (hoisted), fora do nível superior de um arquivo agora lança um erro. O Vitest já içava essas chamadas para o topo do módulo de qualquer forma, então o código dentro de um bloco describe nunca era executado onde foi escrito.
// Vitest 5.0.x: throws
describe('UserCard', () => {
const fetchUser = vi.fn()
vi.mock('./api', () => ({ fetchUser }))
})
// Vitest 5.0.x: works
const { fetchUser } = vi.hoisted(() => ({ fetchUser: vi.fn() }))
vi.mock('./api', () => ({ fetchUser }))
describe('UserCard', () => {
it('renders the user', async () => {
fetchUser.mockResolvedValue({ name: 'Ada' })
// mount and assert
})
})
Se as suas suítes Vue fazem mock da camada de API, o mesmo padrão de nível superior se aplica ao mock de chamadas de API em testes Vue com Vitest.
Asserções sem await
Um teste que deixa uma asserção assíncrona sem await agora falha. A ausência de await antes de expect(...).resolves ou .rejects deixa o teste vermelho.
// Vitest 5.0.x
test('loads config', async () => {
expect(loadConfig()).resolves.toEqual({ ok: true }) // fails
await expect(loadConfig()).resolves.toEqual({ ok: true }) // passes
})
Este grep lista os candidatos. Você ainda precisa verificar se cada ocorrência tem um await antes:
grep -rnE "expect\(.*\)\.(resolves|rejects)" src/ --include='*.test.*' --include='*.spec.*'
Concorrência, busca de config e bench
As opções sequential em testes e suítes foram removidas. Para desativar a concorrência, use test('example', { concurrent: false }, ...) ou describe('suite', { concurrent: false }, ...).
O Vitest 5 deixa de procurar um arquivo de config nas pastas acima da atual. Se você executa vitest a partir de uma subpasta de pacote, essa pasta precisa da sua própria config.
A API de bench foi reescrita. Você não importa mais bench no topo de um arquivo. Em vez disso, obtém-no a partir do contexto do teste, dentro de uma chamada test() comum em um arquivo de benchmark.
As notas de lançamento listam outros itens incompatíveis que você deve verificar, caso se apliquem ao seu projeto:
expect.pollagora falha quando atinge o tempo limite.- Pontos de entrada obsoletos foram removidos.
@vitest/runnerestá obsoleto, evitestnão depende mais de@vitest/expect, porque o código de asserção agora é distribuído dentro do própriovitest.- O provider
@vitest/browser-webdriveriofoi movido para a organização vitest-community e agora é mantido pela comunidade. workerIdagora começa em 1.
toThrow('') agora corresponde a qualquer erro lançado. Se você realmente quer verificar uma mensagem vazia, passe uma regex como /^$/.
O que muda silenciosamente no Vitest 5?
Seis mudanças do Vitest 5 não lançam erro. Em vez disso, um caminho, um filtro ou um resultado de correspondência muda por baixo da sua configuração existente.
- Caminhos de saída. Relatórios blob e
--merge-reportsusam.vitest/blob/por padrão. Os anexos passam de.vitest-attachements/para.vitest/attachments/. Os arquivos dos reporters JSON, JUnit e HTML também usam.vitestpor padrão. - Filtros
-t. O separador dos filtros por nome de teste agora é>. Verifique todos os scripts de CI que filtram pelo caminho da suíte. - Locators do navegador.
locators.exactagora vem ativado por padrão no Browser Mode. - Correspondência de texto.
toHaveTextContentagora é estrito.toMatchTextContenté a nova alternativa. - Globs de cobertura. Os padrões
includeeexcludeagora são comparados com o caminho de cada arquivo relativo à raiz do projeto, e um padrão sem curinga é tratado como uma pasta inteira. O conjunto de arquivos considerados na cobertura pode mudar, então verifique seus limites (thresholds) após a primeira execução. - Projetos inline. Os projetos inline agora herdam a config raiz como se
extends: trueestivesse definido.
Uma etapa típica de artefatos muda assim:
- path: .vitest-attachements/
+ path: .vitest/attachments/
+ # sharded runs: upload .vitest/blob/ for --merge-reports
Novidades do Vitest 5 que vale a pena conhecer
vi.when permite definir um resultado diferente de um spy para cada conjunto de argumentos. calledWith aceita matchers assimétricos, e chamadas cujos argumentos não correspondem a nada recorrem à implementação original.
// Vitest 5.0.x
vi.when(getUser).calledWith(1).thenResolve({ id: 1, name: 'Ada' })
No Browser Mode, definir test.browser.traceView: true ativa a visualização de trace. Cada interação, asserção e chamada a page.mark é salva como um snapshot do DOM, permitindo reproduzir o teste passo a passo na interface.
Projetos aninhados agora são suportados, o que ajuda monorepos a agrupar projetos relacionados.
Checklist de atualização para o Vitest 5
- Migre os ambientes de CI e locais para Node.js 22.12.0+ e Vite 6.4.0+.
- Execute o grep acima e adicione
awaitonde estiver faltando. - Mova todas as chamadas
vi.mockevi.hoistedpara o nível superior dos respectivos arquivos. - Substitua
sequentialpor{ concurrent: false }e adicione configs às pastas de pacotes que dependiam de uma config em um diretório pai. - Execute a suíte. Se asserções de contagem de chamadas falharem, corrija-as ou defina
clearMocks: falsecomo solução temporária. - Atualize os caminhos de artefatos do CI para
.vitest/e revise os filtros-te os limites de cobertura.
Atualizar para o Vitest 5 agora ou esperar?
Atualize para o Vitest 5 nesta sprint se o seu CI já roda Node.js 22.12.0+ e Vite 6.4.0+. A maior parte das edições necessárias é mecânica.
A exceção é uma suíte que faz asserções sobre o histórico de chamadas de mocks herdado entre testes, seja de arquivos de setup, de hooks beforeAll ou de um teste que depende das chamadas de outro. Essas falhas não dão nenhuma pista da causa, então audite essas asserções primeiro e só depois atualize. Suítes de componentes também devem reexecutar suas asserções de texto e de locators. Os padrões em testando componentes Svelte 5 com Vitest mostram onde elas costumam aparecer.
O Vitest 5 é mais rápido, e a maior parte do que ele quebra é código de teste que já estava errado. Comece pelo grep e pela movimentação dos vi.mock em uma branch, verifique os caminhos de artefatos do CI e deixe a primeira execução do CI apontar o restante.
Perguntas frequentes
O Vitest 5 também ativa mockReset ou restoreMocks por padrão?
Não. O guia de migração do Vitest 5 altera o padrão apenas de clearMocks. clearMocks chama vi.clearAllMocks() antes de cada teste e redefine mock.calls, mock.instances, mock.contexts e mock.results, mas mantém as implementações. mockReset vai além: limpa o histórico e redefine cada implementação para a original, de modo que um mock criado com vi.fn(impl) volta a impl. restoreMocks restaura as implementações originais dos spies criados com vi.spyOn.
Por que meu filtro -t corresponde a menos testes após atualizar para o Vitest 5?
No Vitest 5, testNamePattern (a flag -t) é comparado com o nome completo do teste, montado com ' > ' entre o nome de cada suíte e o nome do teste. É o mesmo texto que aparece na saída do reporter. O Vitest 4 usava um único espaço entre as partes, como o Jest. Um padrão só quebra se atravessar de uma parte do nome para a seguinte. Para corrigir, corresponda a apenas uma parte, como -t adds, ou coloque um curinga entre as partes, como -t 'math.*adds'.
Por que o Vitest 5 não consegue resolver o vite após a atualização com Yarn?
No Vitest 5, o vite deixou de ser uma dependência direta e passou a ser uma peer dependency obrigatória, então o Vitest roda com a versão do Vite instalada no seu projeto. npm, pnpm, Bun e Deno adicionam peer dependencies automaticamente. O Yarn deixa essa etapa por sua conta. Adicione o vite na versão 6.4.0 ou posterior ao seu package.json e reinstale as dependências; assim, o Vitest volta a conseguir resolvê-lo.
Como mesclar relatórios de testes fragmentados (sharding) no Vitest 5?
Execute cada shard com o reporter blob, por exemplo vitest run --reporter=blob --shard=1/3 na primeira máquina. Cada shard grava seus resultados em .vitest/blob/ por padrão, e a flag --outputFile.blob altera esse local. Copie o diretório de todas as máquinas para um único job final e execute vitest --merge-reports. Se os seus testes salvam anexos como arquivos, leve também a pasta de anexos para o job de mesclagem.
Gain Debugging Superpowers
Unleash the power of session replay to reproduce bugs, track slowdowns and uncover frustrations in your app. Get complete visibility into your frontend with OpenReplay — the most advanced open-source session replay tool for developers.
Star on GitHub12k