12k
All articles

Was sich in Vitest 5 geändert hat

Erfahren Sie, was sich in Vitest 5 ändert: Leistung, inkompatible Änderungen, neue Standardwerte, Berichtspfade und eine Checkliste für die Migration von Tests und CI.

OpenReplay Team
OpenReplay Team
Was sich in Vitest 5 geändert hat

Vitest 5.0 ist am 3. September 2026 erschienen. Das auf Performance ausgerichtete Major-Release setzt Node.js 22.12.0+ und Vite 6.4.0+ voraus, aktiviert das Zurücksetzen von Mocks standardmäßig, lässt Tests mit nicht abgewarteten asynchronen Assertions fehlschlagen und legt die Reporter-Ausgaben in einem gemeinsamen Verzeichnis .vitest/ ab.

Die meisten Fehler nach dem Upgrade lassen sich leicht beheben. Schwierig sind die Tests, die lokal unter Vitest 4 grün sind und in der CI rot werden, mit einer Fehlermeldung, die nichts über die Ursache verrät.

Dieser Artikel ordnet die Release Notes zu v5.0.0 nach ihrer Auswirkung. Zuerst geht es darum, was tatsächlich schneller geworden ist. Danach folgen die Änderungen, die Codeanpassungen erfordern, die Änderungen, die stillschweigend Pfade und Matching-Regeln verschieben, eine Upgrade-Checkliste und ein Fazit.

Das Wichtigste in Kürze

  • Vitest 5.0 setzt Node.js 22.12.0 oder neuer und Vite 6.4.0 oder neuer voraus.
  • Laut den Benchmarks des Vitest-Teams laufen die meisten getesteten Setups 8 bis 25 % schneller, einige VM-Pool-Setups sogar bis zu 53 %. Setups, deren Laufzeit vom Aufbau der Testumgebung dominiert wird, profitieren kaum.
  • clearMocks ist jetzt standardmäßig true. Eine Assertion auf eine Aufrufhistorie, die in einer Setup-Datei, einem beforeAll-Hook oder einem vorherigen Test aufgezeichnet wurde, sieht daher null Aufrufe.
  • Blob-Reports, Attachments sowie die Ausgaben der JSON-, JUnit- und HTML-Reporter landen standardmäßig unter .vitest/. CI-Schritte für Artefakte müssen deshalb angepasst werden.
  • toThrow('') matcht jetzt jeden geworfenen Fehler. Eine Assertion, die eigentlich auf eine leere Fehlermeldung prüfen soll, braucht ein explizites Pattern.

Warum läuft Vitest 5 schneller?

Laut der Ankündigung zu Vitest 5 laufen die meisten Setups in den Benchmarks des Vitest-Teams 8 bis 25 % schneller. Am stärksten profitieren VM-Pools mit bis zu 53 % in einigen Setups. Nicht jedes Setup wird schneller: Läufe, bei denen das Erzeugen der Testumgebung den Großteil der Zeit ausmacht, etwa forks mit jsdom und Isolation, liegen weiterhin innerhalb von 3 % gegenüber Vitest 4.1. Die Zahlen stammen aus vitest-dev/benchmarks. Dort hat das Team Test-Apps unterschiedlicher Größe generiert, von einem kleinen Paket mit 5 Dateien bis zu einem Monolithen mit 1.280 Modulen. Im Launch-Post von VoidZero wird das auf „vm pools up to 53% faster, ~18% boost across the board including Browser Mode“ gerundet.

Laut den Release Notes gehen die Verbesserungen im Wesentlichen auf vier Änderungen zurück:

  • Gemeinsamer Vite-Server. Inline-Projekte teilen sich jetzt einen Vite-Server, statt jeweils einen eigenen zu starten.
  • fsModuleCache. Diese Option ist jetzt eine Top-Level-Option. Sie speichert transformierte Module auf der Festplatte, sodass ein erneuter Lauf oder ein anderer Vitest-Prozess diese Arbeit überspringen kann.
  • Weniger Roundtrips. Bereits transformierte Module gelangen jetzt in einem einzigen Schritt vom Hauptprozess zum Worker.
  • Wiederverwendung in VM-Pools. Die Pools vmThreads und vmForks teilen kompilierten Code zwischen Kontexten und laden den Modulgraphen vorab.

Vitest unterstützt außerdem den On-Disk-Compile-Cache von Node, dieser muss jedoch explizit aktiviert werden.

Welche Änderungen in Vitest 5 erfordern Codeanpassungen?

Sechs Änderungen in Vitest 5 führen beim ersten Lauf zu einem fehlschlagenden Test oder einem Konfigurationsfehler. Der Migrationsleitfaden behandelt jede davon.

ÄnderungSymptom beim ersten LaufLösung
clearMocks: true als StandardAssertions auf die Aufrufanzahl sehen 0Aufrufe im prüfenden Test auslösen oder clearMocks: false setzen
Nicht abgewartete asynchrone AssertionTest schlägt fehlawait ergänzen
Gehoisteter vi-Aufruf außerhalb der obersten EbeneWirft einen FehlerAuf Modulebene verschieben
sequential entferntAPI existiert nicht mehr{ concurrent: false }
Keine Konfigurationssuche in übergeordneten VerzeichnissenKonfiguration wird nicht gefundenKonfiguration im Paketordner anlegen
Bench-API neu geschriebenAlter Benchmark-Code brichtAuf das Fixture-Modell umstellen

Zurücksetzen und Hoisting von Mocks

In Vitest 5 ist clearMocks standardmäßig true, sodass vor jedem Test vi.clearAllMocks() ausgeführt wird. Eine Aufrufhistorie, die in einer Setup-Datei, einem beforeAll-Hook oder einem vorherigen Test aufgezeichnet wurde, ist bereits gelöscht, bevor der nächste Test darauf prüft. Mock-Implementierungen bleiben erhalten.

// Vitest 5.0.x
const track = vi.fn()
beforeAll(() => initAnalytics(track))

it('tracks once on init', () => {
  expect(track).toHaveBeenCalledTimes(1) // now receives 0 calls
})

Die Lösung besteht darin, den Aufruf in dem Test auszulösen, der ihn prüft. Wenn Sie clearMocks: false in der test-Konfiguration setzen, stellen Sie das alte Verhalten wieder her, solange Sie die Testsuite überprüfen.

Ein Aufruf von vi.mock oder eines anderen gehoisteten vi-Aufrufs an einer anderen Stelle als der obersten Ebene einer Datei wirft jetzt einen Fehler. Vitest hebt diese Aufrufe ohnehin an den Anfang des Moduls, sodass Code innerhalb eines describe-Blocks nie an der Stelle ausgeführt wurde, an der er stand.

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

Wenn Ihre Vue-Testsuites ihre API-Schicht mocken, gilt dasselbe Top-Level-Muster auch für das Mocken von API-Aufrufen in Vue-Tests mit Vitest.

Nicht abgewartete Assertions

Ein Test, der eine asynchrone Assertion nicht abwartet, schlägt jetzt fehl. Ein fehlendes await vor expect(...).resolves oder .rejects färbt den Test rot.

// Vitest 5.0.x
test('loads config', async () => {
  expect(loadConfig()).resolves.toEqual({ ok: true }) // fails
  await expect(loadConfig()).resolves.toEqual({ ok: true }) // passes
})

Dieser grep-Befehl listet potenzielle Kandidaten auf. Sie müssen trotzdem jeden Treffer darauf prüfen, ob ein await vorangestellt ist:

grep -rnE "expect\(.*\)\.(resolves|rejects)" src/ --include='*.test.*' --include='*.spec.*'

Nebenläufigkeit, Konfigurationssuche und Bench

Die sequential-Optionen für Tests und Suites wurden entfernt. Um Nebenläufigkeit zu deaktivieren, verwenden Sie test('example', { concurrent: false }, ...) oder describe('suite', { concurrent: false }, ...).

Vitest 5 sucht nicht mehr in übergeordneten Ordnern nach einer Konfigurationsdatei. Wenn Sie vitest aus einem Unterordner eines Pakets heraus ausführen, benötigt dieser Ordner eine eigene Konfiguration.

Die Bench-API wurde neu geschrieben. Sie importieren bench nicht mehr am Anfang einer Datei, sondern beziehen es aus dem Testkontext innerhalb eines gewöhnlichen test()-Aufrufs in einer Benchmark-Datei.

Die Release Notes führen weitere Breaking Changes auf, die Sie prüfen sollten, sofern sie Sie betreffen:

  • expect.poll schlägt jetzt fehl, wenn das Timeout erreicht wird.
  • Veraltete Entry Points wurden entfernt.
  • @vitest/runner ist als veraltet markiert, und vitest hängt nicht mehr von @vitest/expect ab, da der Assertion-Code jetzt direkt in vitest enthalten ist.
  • Der Provider @vitest/browser-webdriverio ist in die Organisation vitest-community umgezogen und wird nun von der Community gepflegt.
  • workerId beginnt jetzt bei 1.

toThrow('') matcht jetzt jeden geworfenen Fehler. Wenn Sie tatsächlich auf eine leere Fehlermeldung prüfen möchten, übergeben Sie stattdessen einen regulären Ausdruck wie /^$/.

Was ändert sich in Vitest 5 stillschweigend?

Sechs Änderungen in Vitest 5 werfen keinen Fehler. Stattdessen ändert sich unter Ihrem bestehenden Setup ein Pfad, ein Filter oder ein Matching-Ergebnis.

  • Ausgabepfade. Blob-Reports und --merge-reports verwenden standardmäßig .vitest/blob/. Attachments wandern von .vitest-attachements/ nach .vitest/attachments/. Auch die Dateien der JSON-, JUnit- und HTML-Reporter landen standardmäßig in .vitest.
  • -t-Filter. Das Trennzeichen für Filter nach Testnamen ist jetzt >. Prüfen Sie alle CI-Skripte, die nach Suite-Pfaden filtern.
  • Browser-Locators. locators.exact ist im Browser Mode jetzt standardmäßig aktiviert.
  • Text-Matching. toHaveTextContent arbeitet jetzt strikt. toMatchTextContent ist die neue Alternative.
  • Coverage-Globs. include- und exclude-Patterns werden jetzt gegen den Pfad jeder Datei relativ zum Projekt-Root abgeglichen, und ein Pattern ohne Wildcard gilt als ganzer Ordner. Die Menge der für die Coverage berücksichtigten Dateien kann sich dadurch ändern. Prüfen Sie daher nach dem ersten Lauf Ihre Schwellenwerte.
  • Inline-Projekte. Inline-Projekte erben jetzt die Root-Konfiguration, als wäre extends: true gesetzt.

Ein typischer Artefakt-Schritt ändert sich folgendermaßen:

-          path: .vitest-attachements/
+          path: .vitest/attachments/
+          # sharded runs: upload .vitest/blob/ for --merge-reports

Neu in Vitest 5 und wissenswert

Mit vi.when können Sie einem Spy für unterschiedliche Argumentkombinationen jeweils ein anderes Ergebnis zuweisen. calledWith akzeptiert asymmetrische Matcher, und Aufrufe, deren Argumente auf nichts passen, fallen auf die ursprüngliche Implementierung zurück.

// Vitest 5.0.x
vi.when(getUser).calledWith(1).thenResolve({ id: 1, name: 'Ada' })

Im Browser Mode aktiviert test.browser.traceView: true die Trace-Ansicht. Jede Interaktion, jede Assertion und jeder page.mark-Aufruf wird als DOM-Snapshot gespeichert, sodass Sie den Test in der UI Schritt für Schritt nachvollziehen können.

Verschachtelte Projekte werden jetzt unterstützt. Das hilft in Monorepos dabei, zusammengehörige Projekte zu gruppieren.

Checkliste für das Upgrade auf Vitest 5

  1. Stellen Sie CI- und lokale Umgebungen auf Node.js 22.12.0+ und Vite 6.4.0+ um.
  2. Führen Sie den oben gezeigten grep-Befehl aus und ergänzen Sie await überall dort, wo es fehlt.
  3. Verschieben Sie jeden vi.mock- und vi.hoisted-Aufruf auf die oberste Ebene der jeweiligen Datei.
  4. Ersetzen Sie sequential durch { concurrent: false } und legen Sie Konfigurationen in den Paketordnern an, die bisher auf eine übergeordnete Konfiguration angewiesen waren.
  5. Führen Sie die Testsuite aus. Wenn Assertions auf die Aufrufanzahl fehlschlagen, beheben Sie diese oder setzen Sie clearMocks: false als vorübergehende Übergangslösung.
  6. Aktualisieren Sie die CI-Artefaktpfade auf .vitest/ und überprüfen Sie -t-Filter und Coverage-Schwellenwerte.

Sollten Sie jetzt auf Vitest 5 upgraden oder abwarten?

Upgraden Sie noch in diesem Sprint auf Vitest 5, wenn Ihre CI bereits Node.js 22.12.0+ und Vite 6.4.0+ verwendet. Die meisten erforderlichen Anpassungen sind rein mechanisch.

Die Ausnahme bildet eine Testsuite, die auf eine testübergreifende Mock-Aufrufhistorie prüft, sei es aus Setup-Dateien, aus beforeAll-Hooks oder weil ein Test auf die Aufrufe eines anderen Tests angewiesen ist. Diese Fehler geben keinen Hinweis auf ihre Ursache. Überprüfen Sie daher zuerst diese Assertions und führen Sie danach das Upgrade durch. Suites für Komponenten sollten zudem ihre Text- und Locator-Assertions erneut ausführen. Die Muster aus dem Artikel zum Testen von Svelte-5-Komponenten mit Vitest zeigen, wo diese typischerweise vorkommen.

Vitest 5 ist schneller, und das meiste, was dabei bricht, ist Testcode, der ohnehin fehlerhaft war. Beginnen Sie auf einem Branch mit dem grep-Befehl und dem Verschieben der vi.mock-Aufrufe, prüfen Sie die CI-Artefaktpfade und lassen Sie sich vom ersten CI-Lauf den Rest zeigen.

FAQs

Aktiviert Vitest 5 auch mockReset oder restoreMocks standardmäßig?

Nein. Laut Migrationsleitfaden zu Vitest 5 ändert sich der Standardwert nur für clearMocks. clearMocks ruft vor jedem Test vi.clearAllMocks() auf und setzt mock.calls, mock.instances, mock.contexts und mock.results zurück, behält aber die Implementierungen bei. mockReset geht weiter: Es löscht die Historie und setzt jede Implementierung auf ihren Ursprungszustand zurück, sodass ein mit vi.fn(impl) erzeugter Mock wieder impl verwendet. restoreMocks stellt die ursprünglichen Implementierungen von Spies wieder her, die mit vi.spyOn erzeugt wurden.

Warum matcht mein -t-Filter nach dem Upgrade auf Vitest 5 weniger Tests?

In Vitest 5 wird testNamePattern (das Flag -t) gegen den vollständigen Testnamen geprüft, der entsteht, indem ' > ' zwischen jeden Suite-Namen und den Testnamen gesetzt wird. Das ist derselbe Text, den Sie in der Reporter-Ausgabe sehen. Vitest 4 verwendete wie Jest ein einzelnes Leerzeichen zwischen den Teilen. Ein Pattern bricht nur dann, wenn es sich über die Grenze zwischen zwei Namensteilen erstreckt. Zur Behebung matchen Sie nur einen Teil, etwa -t adds, oder setzen Sie eine Wildcard zwischen die Teile, etwa -t 'math.*adds'.

Warum kann Vitest 5 nach dem Upgrade mit Yarn vite nicht auflösen?

In Vitest 5 wurde vite von einer direkten Abhängigkeit zu einer erforderlichen Peer Dependency, sodass Vitest mit der Vite-Version läuft, die in Ihrem Projekt installiert ist. npm, pnpm, Bun und Deno fügen Peer Dependencies automatisch hinzu. Yarn überlässt diesen Schritt Ihnen. Fügen Sie vite in Version 6.4.0 oder neuer zu Ihrer package.json hinzu und installieren Sie die Abhängigkeiten neu, dann kann Vitest es wieder auflösen.

Wie führe ich in Vitest 5 geshardete Test-Reports zusammen?

Führen Sie jeden Shard mit dem Blob-Reporter aus, zum Beispiel vitest run --reporter=blob --shard=1/3 auf der ersten Maschine. Jeder Shard schreibt seine Ergebnisse standardmäßig nach .vitest/blob/; mit dem Flag --outputFile.blob lässt sich dieser Speicherort ändern. Kopieren Sie das Verzeichnis von jeder Maschine in einen abschließenden Job und führen Sie dort vitest --merge-reports aus. Wenn Ihre Tests Attachments als Dateien speichern, übernehmen Sie auch den Attachments-Ordner in den Merge-Job.

DevTools for the frontend

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

We use cookies to improve your experience. By using our site, you accept cookies.