#angular #typescript #unit-testing #jasmine #karma-jasmine
#angular #typescript #модульное тестирование #jasmine #карма-жасмин
Вопрос:
Я пытаюсь проверить, вызывается ли моя функция навигации для удаления транспортного средства. Но, похоже, он никогда не вызывается. Я думаю, что это может иметь какое-то отношение к тому факту, что это асинхронная функция, но даже когда я жду завершения полной подписки, она не работает.
.ts:
deleteVehicle(): void {
if (confirm('Bent u zeker dat u deze wagen wilt verwijderen?')) {
this.apiService.deleteVehicle(this.selectedVehicle.id).subscribe(() => this.navigateToListVehicleComponent());
}
}
spec.ts:
beforeEach(() => {
fixture = TestBed.createComponent(VehicleDetailsComponent);
component = fixture.componentInstance;
apiService = TestBed.get(ApiService);
fixture.detectChanges();
});
describe('#deleteVehicle', () => {
it('should navigate to list vehicle component', fakeAsync(() => {
spyOn(window, 'confirm').and.returnValue(true);
spy = spyOn(apiService, 'deleteVehicle').withArgs(component.selectedVehicle.id).and.callThrough();
let navigateSpy = spyOn(component,'navigateToListVehicleComponent').and.callThrough();
component.deleteVehicle();
tick();
expect(spy).toHaveBeenCalled();
expect(navigateSpy).toHaveBeenCalled();
}));
});
service.ts:
private deleteFromAPI(url): any {
return this.http
.delete(this.BASE_API_URL url)
.pipe(catchError(this.handleError));
}
deleteVehicle(id: number): any {
return this.deleteFromAPI('vehicle/' id);
}
и в моем тестовом модуле я импортирую HttpClientTestingModule.
ошибка: ожидаемый вызов spy navigateToListVehicleComponent .
Кто-нибудь знает, что я делаю не так?
Комментарии:
1. Можете ли вы показать настройки для своих тестов? Вы издевались
apiService.deleteVehicle
над методом?2. @slideshowp2 Я немного изменил код, надеюсь, его легче понять, что я делаю сейчас. Я в основном издеваюсь над своим apiService с помощью HttpClientTestingModule, а затем слежу за apiService. Метод deleteVehicle.
3. Вы используете
callThrough()
which делегирует фактическую реализацию. Это может вызвать проблему. Можете ли вы опубликовать фактическую реализациюapiService.deleteVehicle()
метода?4. Я только что отредактировал сообщение с реализацией apiService. deleteVehicle() надеюсь, это поможет
Ответ №1:
Моя стратегия тестирования заключается в том, чтобы заглушить apiService.deleteVehicle
метод, чтобы он не имел побочного эффекта (отправка реального HTTP-запроса по сети).
решение для модульного тестирования с использованием angular
v11 :
example.component.ts
:
import { Component } from '@angular/core';
import { ApiService } from './api.service';
@Component({})
export class ExampleComponent {
selectedVehicle = {
id: 1,
};
constructor(private apiService: ApiService) {}
navigateToListVehicleComponent() {
console.log('navigateToListVehicleComponent real implementation');
}
deleteVehicle(): void {
if (confirm('Bent u zeker dat u deze wagen wilt verwijderen?')) {
this.apiService
.deleteVehicle(this.selectedVehicle.id)
.subscribe(() => this.navigateToListVehicleComponent());
}
}
}
api.service.ts
:
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { of } from 'rxjs';
import { catchError } from 'rxjs/operators';
@Injectable()
export class ApiService {
BASE_API_URL = 'http://localhost';
constructor(private http: HttpClient) {}
private deleteFromAPI(url): any {
return this.http
.delete(this.BASE_API_URL url)
.pipe(catchError(this.handleError));
}
private handleError(err) {
return of(err);
}
deleteVehicle(id: number): any {
return this.deleteFromAPI('vehicle/' id);
}
}
example.component.spec.ts
:
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { of } from 'rxjs';
import { ApiService } from './api.service';
import { ExampleComponent } from './example.component';
fdescribe('#deleteVehicle', () => {
let apiService: ApiService;
let fixture: ComponentFixture<ExampleComponent>;
let component: ExampleComponent;
beforeEach(
waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ExampleComponent],
imports: [HttpClientModule],
providers: [ApiService, HttpClient],
})
.compileComponents()
.then(() => {
fixture = TestBed.createComponent(ExampleComponent);
apiService = TestBed.get(ApiService);
component = fixture.componentInstance;
fixture.detectChanges();
});
})
);
it('should navigate to list vehicle component', () => {
const confirmSpy = spyOn(window, 'confirm').and.returnValue(true);
const deleteVehicleSpy = spyOn(apiService, 'deleteVehicle')
.withArgs(component.selectedVehicle.id)
.and.returnValue(of('deleteVehicle fake implementation'));
let navigateSpy = spyOn(
component,
'navigateToListVehicleComponent'
).and.stub();
component.deleteVehicle();
expect(confirmSpy).toHaveBeenCalledOnceWith(
'Bent u zeker dat u deze wagen wilt verwijderen?'
);
expect(deleteVehicleSpy).toHaveBeenCalledOnceWith(1);
expect(navigateSpy).toHaveBeenCalled();
});
});
результат модульного теста:
Комментарии:
1. Большое вам спасибо, это исправлено!