I have overridden the @angular/core ErrorHandler and I am trying to test it, however I am getting an error. The service works properly but the test fails somewhere.
exception-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);
  }
}
An here it is the test file
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);
  });
});
And finally the error
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)
Could you guys help me?
I've come across the need to test a class that implements ErrorHandler as well and went down the same path as you (but in my case a mock service that raised an error) and ran into the same problem of test exception forcing the test to fail. This is a text book example of needing to refactor to make something more testable.
It also hit me I wasn't JUST testing my implementation of handleError() but also angular2's ErrorHandler functionality. In other words the level of integration for the test was to high, I just needed to test my ErrorHandlerService service in isolation from angular2's error functionality.
This is what I did
@Injectable()
export class ErrorHandlerService implements ErrorHandler {
  constructor() {}
  handleError(error: any): void {
    this.processError(error);
    throw error;
  }
  public processError(error: any) {
    console.log(error);
  }
}
and the test itself
  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);
  }));
You don't need to actually throw new Error(), The Angular2 team has already confirmed that for you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With