茉莉花:单元测试http服务错误可观察到

时间:2018-07-03 13:56:19

标签: angular unit-testing jasmine karma-jasmine

我对如何模拟我的http服务捕获到一个可观察到的错误感到非常困惑。我已经阅读了有角度的文档,但不了解如何构造测试。我想在服务中模拟错误,然后检查它是否捕获到可观察到的错误。我还有另一个服务可以创建并引发可观察到的错误。我的其余服务只会在遇到错误时捕获它。老实说,我对如何实现这一点感到非常困惑。这是我的服务以及错误服务的简单证明:

getData(url: string): Observable<any> {
    return this.http.get(url)
       .map(this.extractData)
        .catch(this.handleErrorObservable);
}

  handleErrorObservable(error: Response | any) {
    console.error(error.message || error);
    return Observable.throw(error.message || error);
}

现在如何模拟错误?我需要监视服务并使其失败吗?会与spyOn(service, 'getData).and.returnValue(Observable.throw({status: 404})))相似吗?还是我看错了方向?谢谢。

编辑:使用Castro Roy解决方案进行编码。

import {HttpErrorResponse, } from '@angular/common/http';
import { TestBed, inject } from '@angular/core/testing'
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing'
import {HttpService} from '../services/http.service'

fdescribe('MyService', () => {
    let httpTestingController: HttpTestingController;

    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule],
            providers: [HttpService]
        });
        httpTestingController = TestBed.get(HttpTestingController);
    });

    afterEach(() => {

        httpTestingController.verify();
    });

    it('should be created', inject([HttpService], (service: HttpService)=> {
        expect(service).toBeTruthy();
    }));

    it('should handleErrorObservable', inject([HttpService], (service: HttpService) => {
        const urlString = '/data';
        const emsg = 'deliberate 404 error';

        spyOn(service, 'handleErrorObservable').and.callThrough();

        service.getData(urlString).subscribe(
            data => fail('should have failed with the 404 error'),
            (error: HttpErrorResponse) => {

              expect(service.handleErrorObservable).toHaveBeenCalled(); // check if executed

              expect(error.status).toEqual(404, 'status');
              expect(error.error).toEqual(emsg, 'message');

             });

        const req = httpTestingController.expectOne(urlString);


        req.flush(emsg, { status: 404, statusText: 'Not Found' });
      }));
});

1 个答案:

答案 0 :(得分:3)

如果尝试将spyOn(service, 'getData').and.returnValue(Observable.throw({status: 404})))模拟到其他使用它的服务,则

getData migth很有用,但是handleErrorObservable将永远不会执行。因此,如果您想测试是否已调用handleErrorObservable,类似的方法应该可以帮助您:

import { HttpErrorResponse } from '@angular/common/http';
import { TestBed, inject } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';

import { MyService } from './MyService';

describe('MyService', () => {
  let httpTestingController: HttpTestingController;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [MyService]
    });

    httpTestingController = TestBed.get(HttpTestingController);
  });

  afterEach(() => {
    // After every test, assert that there are no more pending requests.
    httpTestingController.verify();
  });

  it('should be created', inject([MyService], (service: MyService) => {
    expect(service).toBeTruthy();
  }));

  it('should handleErrorObservable', inject([MyService], (service: MyService) => {
    const urlString = '/data';
    const emsg = 'deliberate 404 error';

    spyOn(service, 'handleErrorObservable').and.callThrough();

    service.getData(urlString).subscribe(
        data => fail('should have failed with the 404 error'),
        (error: HttpErrorResponse) => {

          expect(service.handleErrorObservable).toHaveBeenCalled(); // check if executed

          expect(error.status).toEqual(404, 'status');
          expect(error.error).toEqual(emsg, 'message');
        }
    });

    const req = httpTestingController.expectOne(urlString);

    // Respond with mock error
    req.flush(emsg, { status: 404, statusText: 'Not Found' });
  }));
});

在这里,我们使用HttpClientTestingModuleHttpTestingController模拟状态代码为404的错误响应。将MyService更改为您的服务名称,并在此示例中稍作介绍,它将需要进行一些更改以使其适应您的需求。 More info in the docs

另外,将a look to another question带到正在使用另一种模拟HttpClient服务的方式。

希望有帮助。