简体   繁体   English

如何测试 Angular 2 ErrorHandler 实现?

[英]How can I test an Angular 2 ErrorHandler implementation?

I have overridden the @angular/core ErrorHandler and I am trying to test it, however I am getting an error.我已经覆盖了@angular/core ErrorHandler 并且我正在尝试对其进行测试,但是我收到了一个错误。 The service works properly but the test fails somewhere.该服务工作正常,但测试在某处失败。

exception-handler.service.ts异常处理程序.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.我遇到了需要测试一个也实现 ErrorHandler 的类,并沿着与您相同的路径(但在我的情况下是一个引发错误的模拟服务)并遇到了相同的测试异常问题,迫使测试失败。 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.它也让我感到震惊,我不仅测试了我的handleError()实现,还测试了 angular2 的 ErrorHandler 功能。 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.换句话说,测试的集成度很高,我只需要测试我的ErrorHandlerService服务,将其与 angular2 的错误功能隔离开来。

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.您实际上不需要throw new Error() ,Angular2 团队已经为您确认了这一点。

I would suggest two different testing scenarios:我会建议两种不同的测试场景:

One where you do actual unit testing of your "BkExceptionHandlerService", calling the "handleError" method directly, spying and mocking what you need to cover all the scenarios.一种你对“BkExceptionHandlerService”进行实际单元测试的地方,直接调用“handleError”方法,监视和模拟覆盖所有场景所需的内容。

And an integration test where you actually overwrite the provider of "ErrorHandler" with your custom "BkExceptionHandlerService" and then you check that when you try to inject an instance of "ErrorHandler", it returns an instance of your "BkExceptionHandlerService"还有一个集成测试,您实际上用自定义的“BkExceptionHandlerService”覆盖“ErrorHandler”的提供者,然后检查当您尝试注入“ErrorHandler”的实例时,它会返回“BkExceptionHandlerService”的实例

For example (inspired from here https://github.com/angular/angular/blob/3a60063a54d850c50ce962a8a39ce01cfee71398/aio/src/app/shared/reporting-error-handler.spec.ts ), assuming that you are overwriting the dependency in your "AppModule"例如(灵感来自这里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));
});

You really shouldn't test that when you trigger an error, your error handler catches it because you'd be testing the framework instead of your code.你真的不应该测试当你触发一个错误时,你的错误处理程序会捕获它,因为你将测试框架而不是你的代码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM