Mit Angular Version 21 ist die Test-Bibliothek „Vitest“ nun Standard für neue Projekte und ersetzt Karma/Jasmin. Solche Art von Neuigkeiten ist oft der Schrecken für bestehende Projekt. In diesem Fall können wir uns aber (fast) bequem zurücklehnen. Bevor wir uns die Migration anschauen hier die wichtigsten Punkte, die es über Vitest zu wissen gibt:
- Syntax sehr (sehr) ähnlich zu Jasmine
- (im Standard) kein Test in echten Browser Instanzen (wesentlich performanter)
- automatische Migration via CLI möglich.
Schauen wir uns an, was eine Migration bedeutet.
npm install --save-dev vitest jsdom
Installiert die benötigten Abhängigkeiten im Projekt. Zusätzlich bedarf es noch einer Anpassung der Test-Konfiguration in der Datei angular.json
"test": {
"builder": "@angular/build:unit-test"
}
Ersetzt den Builder: „@angular/build:karma“, auch die dort hinterlegten Optionen können in aller Regel entfernt werden.
ng g @schematics/angular:refactor-jasmine-vitest
Führt eine automatische Migration alle Test-Fälle durch. Zumindest theoretisch. In meinem Fall hat das Hinzufügen der Import-Deklaration leider nicht funktioniert und auch das Erzeugen von Spy-Objekten (createSpyObj) scheint in der automatischen Migration nicht berücksichtigt zu werden. Schauen wir uns an einem Test die Unterschiede an:
// Jasmine
spyOn(TestBed.inject(TimeService), 'calculateDuration').and.returnValue(Duration.fromISO('PT1H'));
// Vitest (automatisch migriert)
vi.spyOn(TestBed.inject(TimeService), 'calculateDuration').mockReturnValue(Duration.fromISO('PT1H'));
// Jasmine
expect(TestBed.inject(RecordService).load).toHaveBeenCalledOnceWith();
// Vitest (automatisch migriert)
expect(TestBed.inject(RecordService).load).toHaveBeenCalledTimes(1);
expect(TestBed.inject(RecordService).load).toHaveBeenCalledWith();
// Jasmine
const recordServiceMock = createSpyObj<RecordService>('RecordService', ['load'])
recordServiceMock.load.and.returnValue(of([
{...},
{...}
]));
// Vitest (NICHT automatisch migriert)
const recordServiceMock = {
load: vi.fn().mockReturnValue(of([
{...},
{...}
]))
}
Wie wir sehen können, ist die Umgewöhnung auf die neue Syntax eher überschaubar und dank der automatischen Migration hält sich der Umstellungswaufwand in Grenzen. Hier und da werden aber sicherlich manuelle Schritte notwenig sein, wie hier im Beispiel schon zu sehen.







