Как я могу проверить реализацию Angular 2 ErrorHandler?
Я переопределил @angular/core ErrorHandler и пытаюсь его проверить, однако получаю ошибку. Сервис работает нормально, но тест где-то не проходит.
исключение-handler.service.ts
import { Injectable, ErrorHandler, forwardRef, Inject } from '@angular/core';
import { BkHttp } from './http.service';
@Injectable()
export class BkExceptionHandlerService implements ErrorHandler {
constructor( private bkHttp: BkHttp) { }
handleError(error) {
let originalError = this.controlError(error);
this.sendToConsole(originalError);
this.sendToBitacora( originalError );
throw( error );
}
controlError(error: any): any {
let originalError: Object = this.findOriginalError( error );
return originalError;
}
findOriginalError( error: any ) : any {
while ( error && error.originalError ) {
error = error.originalError;
}
return( error );
}
getPrueba():string {
return 'prueba!!!';
}
sendToConsole(error:any): void {
try {
console.group( 'START ErrorHandler' );
console.error( error );
console.error( error.message );
console.error( error.stack );
console.groupEnd();
} catch (handlingError) {
console.group( 'START ErrorHandler' );
console.warn( 'Error when trying to output error. Pure Irony' );
console.error( handlingError );
console.groupEnd();
}
}
sendToBitacora(error:any): void {
let body: Object = {
name: error.name,
message: error.message,
stack: error.stack,
location: window.location.href
};
this.bkHttp.post('http://google.es', body).subscribe(res => { });
//this.bkHttp.post('http://fgooffglffffe.es', body);
}
}
А вот это тестовый файл
import { Component, DebugElement } from '@angular/core';
import { TestBed, ComponentFixture, async } from '@angular/core/testing';
import { By } from '@angular/platform-browser';
import { Observable } from 'rxjs';
import { Response, Http } from '@angular/http';
import { BkHttp } from './http.service';
import { BkExceptionHandlerService } from './exception-handler.service';
const ERROR_MESSAGE = 'Dummy Error';
@Component({
selector: 'dummy-component',
template: `<button (click)="throwError()">Throw an error!!!</button>`
})
export class MockComponent {
public throwError(): void {
throw Error(ERROR_MESSAGE);
}
}
describe('FancyService without the TestBed', () => {
let bkExceptionHandlerService: BkExceptionHandlerService;
let bkHttp: BkHttp;
let fixture: ComponentFixture<MockComponent>;
let loggerSpy: jasmine.Spy;
let consoleSpy: jasmine.Spy;
let errorObservableSpy: jasmine.Spy;
let comp: MockComponent;
beforeEach( async(() => {
TestBed.configureTestingModule({
declarations: [ MockComponent ],
})
.compileComponents(); // compile template and css
}));
beforeEach(() => {
bkExceptionHandlerService = new BkExceptionHandlerService(bkHttp);
loggerSpy = spyOn(bkExceptionHandlerService, 'controlError').and.callThrough();
consoleSpy = spyOn(console, 'error');
errorObservableSpy = jasmine.createSpy('log event observable subscription');
fixture = TestBed.createComponent(MockComponent);
comp = fixture.componentInstance;
fixture = TestBed.createComponent(MockComponent);
});
it('should log error to the console', () => {
let elem = fixture.debugElement.query(By.css('button'));
elem.triggerEventHandler('click', null);
expect(loggerSpy).toHaveBeenCalledWith(jasmine.any(Error), ERROR_MESSAGE);
});
});
И наконец ошибка
Error: Error in ./MockComponent class MockComponent - inline template:0:0 caused by: Dummy Error in node_modules/@bankular/development-tools/config/karma-test-shim.js (line 49231)
Не могли бы вы, ребята, помочь мне?
2 ответа
Я столкнулся с необходимостью протестировать класс, который также реализует ErrorHandler, и пошел по тому же пути, что и вы (но в моем случае это фиктивный сервис, который вызвал ошибку), и столкнулся с той же проблемой тестовых исключений, заставляющих тест потерпеть поражение. Это пример из учебника о необходимости рефакторинга, чтобы сделать что-то более тестируемое.
Меня также поразило, что я не просто тестировал мою реализацию handleError(), но и функцию Angular2 ErrorHandler. Другими словами, уровень интеграции для теста был слишком высок, мне просто нужно было протестировать мой сервис ErrorHandlerService в отрыве от функции ошибок angular2.
Это то что я сделал
@Injectable()
export class ErrorHandlerService implements ErrorHandler {
constructor() {}
handleError(error: any): void {
this.processError(error);
throw error;
}
public processError(error: any) {
console.log(error);
}
}
и сам тест
it('correctly handles error', inject([ErrorHandlerService], (service: ErrorHandlerService) => {
const spy = spyOn(console, 'log');
const error: Error = new Error('ERROR');
service.processError(error);
expect(spy).toHaveBeenCalledWith(error);
}));
Вам не нужно на самом деле throw new Error()
Команда Angular2 уже подтвердила это для вас.
Я бы предложил два разных сценария тестирования:
Тот, в котором вы выполняете фактическое модульное тестирование вашего «BkExceptionHandlerService», напрямую вызывая метод «handleError», шпионя и издеваясь над тем, что вам нужно, чтобы охватить все сценарии.
И интеграционный тест, в котором вы фактически перезаписываете поставщика «ErrorHandler» своим пользовательским «BkExceptionHandlerService», а затем проверяете, что при попытке внедрить экземпляр «ErrorHandler» он возвращает экземпляр вашего «BkExceptionHandlerService».
Например (вдохновленный здесь https://github.com/angular/angular/blob/3a60063a54d850c50ce962a8a39ce01cfee71398/aio/src/app/shared/reporting-error-handler.spec.ts), предполагая, что вы перезаписываете зависимость в своем "Модуль приложения"
it('should be registered on the AppModule', () => {
handler = TestBed.configureTestingModule({ imports: [AppModule] }).inject(ErrorHandler) as any;
expect(handler).toEqual(jasmine.any(BkExceptionHandlerService));
});
Вы действительно не должны проверять, что когда вы вызываете ошибку, ваш обработчик ошибок ловит ее, потому что вы будете тестировать фреймворк, а не свой код.