Angular2单元测试Jasmine测试控制台错误和变量内部回调函数

时间:2017-05-17 11:35:11

标签: angular

我想知道对这个简单函数进行100%覆盖的确切方法,但似乎无法做到正确。

命名-list.service.ts

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
// import 'rxjs/add/operator/do';  // for debugging

/**
 * This class provides the NameList service with methods to read names and add names.
 */
@Injectable()
export class NameListService {

  /**
   * Creates a new NameListService with the injected Http.
   * @param {Http} http - The injected Http.
   * @constructor
   */
  constructor(private http: Http) {}

  /**
   * Returns an Observable for the HTTP GET request for the JSON resource.
   * @return {string[]} The Observable for the HTTP request.
   */
  get(): Observable<string[]> {
    return this.http.get('assets/data.json')
                    .map((res: Response) => res.json())
    //              .do(data => console.log('server data:', data))  // debug
                    .catch(this.handleError);
  }

  /**
    * Handle HTTP error
    */
  private handleError (error: any) {
    // In a real world app, we might use a remote logging infrastructure
    // We'd also dig deeper into the error to get a better message
    let errMsg = (error.message) ? error.message :
      error.status ? `${error.status} - ${error.statusText}` : 'Server error';
    console.error(errMsg); // log to console instead
    return Observable.throw(errMsg);
  }
}

和当前的单元测试

命名-list.service.spec.ts

import { BaseRequestOptions, ConnectionBackend, Http, Response, ResponseOptions } from '@angular/http';
import { TestBed, async } from '@angular/core/testing';
import { MockBackend } from '@angular/http/testing';

import { Observable } from 'rxjs/Observable';

import { NameListService } from './name-list.service';

export function main() {
  describe('NameList Service', () => {
    let nameListService: NameListService;
    let mockBackend: MockBackend;

    beforeEach(() => {

      TestBed.configureTestingModule({
        providers: [
          NameListService,
          MockBackend,
          BaseRequestOptions,
          {
            provide: Http,
            useFactory: (backend: ConnectionBackend, options: BaseRequestOptions) => new Http(backend, options),
            deps: [MockBackend, BaseRequestOptions]
          }
        ]
      });
    });




    it('should return an Observable when get called', async(() => {
      expect(TestBed.get(NameListService).get()).toEqual(jasmine.any(Observable));
    }));


    it('should resolve to list of names when get called', async(() => {
      let nameListService = TestBed.get(NameListService);
      let mockBackend = TestBed.get(MockBackend);

      mockBackend.connections.subscribe((c: any) => {
        c.mockRespond(new Response(new ResponseOptions({ body: '["Dijkstra", "Hopper"]' })));
      });

      nameListService.get().subscribe((data: any) => {
        expect(data).toEqual(['Dijkstra', 'Hopper']);
      });
    }));

    beforeEach(function(){
      spyOn(console, 'error');
    })
    it('should throw an Observable when get called', (() => {
      let nameListService = TestBed.get(NameListService);
      let err = {
        message: "Some error", status: 500, statusText: "Some error text"
      };
      expect(nameListService.handleError(err)).toEqual(jasmine.any(Observable))
    }));


  });
}

如何测试 errMsg 变量和 console.error 以获得100%的覆盖率?

1 个答案:

答案 0 :(得分:1)

这应该逐行测试,就像它总是在单元测试中一样。

如果它是一个回调函数,它的调用应该与它应该完全相同,即没有上下文。

it('should throw an Observable when get called', fakeAsync(() => {
  ...
  const errObservable = nameListService.handleError.call(null, err);

  expect(console.error).toHaveBeenCalledWith('Some error');
  expect(errObservable).toEqual(jasmine.any(Observable));
  errObservable.toPromise().then(
    () => { throw new Error('shouldn't be resolved') }),
    errMsg => {
      expect(errMsg).toBe('Some error');
    })
  );
}));

然后对没有err属性的message对象执行相同的操作。

toPromise在这里很有用,因为如果observable为空,它将无法通过测试,而subscribe永远不会被触发。