Unit Testig
Was ist Unit Testing?¶
Unit Testing bedeutet, kleine, isolierte Einheiten eines Programms (wie eine Funktion, eine Klasse oder eine Methode) zu testen, um sicherzustellen, dass sie korrekt funktionieren. In Angular konzentriert sich das Unit Testing oft auf Komponenten, Services, Direktiven oder Pipes.
Warum ist Unit Testing wichtig?¶
- Frühzeitige Fehlererkennung: Probleme werden erkannt, bevor sie grössere Teile der Anwendung beeinflussen.
- Sicheres Refactoring: Änderungen am Code können gemacht werden, ohne bestehende Funktionen unbeabsichtigt zu brechen.
- Bessere Wartbarkeit: Tests dienen als Dokumentation und helfen Entwicklern, den Code zu verstehen.
- Automatisierung: Tests können automatisiert ausgeführt werden, um wiederkehrende Aufgaben zu erleichtern.
Wie funktioniert Unit Testing in Angular?¶
Angular verwendet zwei wichtige Tools für das Testen: 1. Jasmine: Eine Testing-Bibliothek, die Test-Syntax und -Methoden bereitstellt. 2. Karma: Ein Test-Runner, der Tests in verschiedenen Browsern ausführt.
Testdateien enden auf .spec.ts und werden automatisch von Angular CLI erstellt, wenn man neue Komponenten oder Services erzeugt.
Grundstruktur eines Tests¶
Ein Test besteht in Angular aus einer Test-Suite (beschrieben mit describe) und einzelnen Tests (beschrieben mit it).
Beispiel: Einfache Funktion testen¶
// Funktion, die wir testen wollen
export function add(a: number, b: number): number {
return a + b;
}
// Test für diese Funktion
describe('add', () => {
it('should return the sum of two numbers', () => {
const result = add(2, 3);
expect(result).toBe(5); // Erwartet, dass 2 + 3 = 5 ergibt
});
it('should return a negative number when sum is negative', () => {
const result = add(-2, -3);
expect(result).toBe(-5);
});
});
Unit Testing einer Angular-Komponente¶
Komponenten sind der Kern einer Angular-Anwendung. Tests für Komponenten prüfen z. B.: - Ob sie korrekt erstellt wird. - Ob sie das richtige HTML rendert. - Ob Benutzeraktionen wie Klicks die erwarteten Ergebnisse liefern.
Beispiel: Komponente testen¶
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { MyComponent } from './my.component';
describe('MyComponent', () => {
let component: MyComponent;
let fixture: ComponentFixture<MyComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [MyComponent]
}).compileComponents();
fixture = TestBed.createComponent(MyComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create the component', () => {
expect(component).toBeTruthy(); // Prüft, ob die Komponente erstellt wurde
});
it('should display the correct title', () => {
component.title = 'Hello Angular';
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello Angular');
});
});
In diesem Beispiel wird geprüft, ob: 1. Die Komponente erfolgreich erstellt wurde. 2. Der Titel der Komponente korrekt im HTML angezeigt wird.
Services testen¶
Services enthalten oft Geschäftslogik und Datenverarbeitung. Unit Tests prüfen, ob diese Logik korrekt arbeitet.
Beispiel: Service testen¶
import { TestBed } from '@angular/core/testing';
import { MyService } from './my.service';
describe('MyService', () => {
let service: MyService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MyService);
});
it('should return the correct data', () => {
const data = service.getData();
expect(data).toEqual(['Angular', 'Unit Testing', 'Jasmine']);
});
});
Abhängigkeiten simulieren (Mocks und Spies)¶
Oft greifen Einheiten auf externe Abhängigkeiten wie HTTP-Requests oder andere Services zu. Statt echte Implementierungen zu verwenden, können Mocks oder Spies verwendet werden.
Beispiel: Mock eines Services¶
import { TestBed } from '@angular/core/testing';
import { MyService } from './my.service';
import { MyComponent } from './my.component';
describe('MyComponent with MockService', () => {
let component: MyComponent;
let mockService: jasmine.SpyObj<MyService>;
beforeEach(() => {
const spy = jasmine.createSpyObj('MyService', ['getData']);
TestBed.configureTestingModule({
declarations: [MyComponent],
providers: [{ provide: MyService, useValue: spy }]
});
component = TestBed.createComponent(MyComponent).componentInstance;
mockService = TestBed.inject(MyService) as jasmine.SpyObj<MyService>;
});
it('should use mock data', () => {
mockService.getData.and.returnValue(['Mocked Data']);
component.loadData();
expect(component.data).toEqual(['Mocked Data']);
});
});
Zusammenfassung der wichtigsten Begriffe¶
- TestBed: Zum Erstellen und Initialisieren von Angular-Komponenten und -Services im Test.
- Fixture: Repräsentiert eine Instanz der Komponente im Test.
- Spies: Werkzeuge, um Methoden zu überwachen oder zu manipulieren.
- Mocks: Simulation von Abhängigkeiten, um echte Implementierungen zu vermeiden.
Fazit¶
Unit Testing in Angular hilft dabei: - Den Code stabil und zuverlässig zu halten. - Fehler frühzeitig zu erkennen. - Änderungen sicher umzusetzen.
Es ist eine grundlegende Fähigkeit, die bei der Entwicklung moderner Anwendungen unverzichtbar ist. Indem einfache Tests geschrieben werden, kann die Qualität und Wartbarkeit der Software erheblich verbessert werden.