如何测试(Jasmine)服务实际上处理模拟HTTP错误的错误

时间:2017-05-02 16:25:31

标签: angular typescript error-handling jasmine karma-jasmine

我有一个Angular服务,通过Swagger生成。

该服务只进行HTTP调用并返回用户列表。我设法为“成功”调用正确编写测试用例。

然而,我很难为“失败”案件进行测试。

我试图简单地调用函数并通过模拟响应,创建一个“错误”响应,但它似乎无法检测到实际抛出了异常。

您将在下面找到服务和我的测试用例:

service.ts

getListUsers(): Observable<UsersListModel | null> {
    let url_ = this.baseUrl + "/api/users";
    url_ = url_.replace(/[?&]$/, "");

    const content_ = "";

    let options_ = {
        body: content_,
        method: "get",
        headers: new Headers({
            "Content-Type": "application/json; charset=UTF-8", 
            "Accept": "application/json; charset=UTF-8"
        })
    };

    return this.http.request(url_, options_).flatMap((response_) => {
        return this.processGetListUsers(response_);
    }).catch((response_: any) => {
        if (response_ instanceof Response) {
            try {
                return this.processGetListActivities(response_);
            } catch (e) {
                return <Observable<UsersListModel>><any>Observable.throw(e);
            }
        } else
            return <Observable<UsersListModel>><any>Observable.throw(response_);
    });
}

protected processGetListUsers(response: Response): Observable<UsersListModel | null> {
    const status = response.status; 

    if (status === 200) {
        const responseText = response.text();
        let result200: UsersListModel | null = null;
        let resultData200 = responseText === "" ? null : JSON.parse(responseText, this.jsonParseReviver);
        result200 = resultData200 ? UsersListModel.fromJS(resultData200) : <any>null;
        return Observable.of(result200);
    } else if (status !== 200 && status !== 204) {
        const responseText = response.text();
        return throwException("An unexpected server error occurred.", status, responseText);
    }
    return Observable.of<UsersListModel | null>(<any>null);
}

spec文件

describe('ERROR on Get Users List', () => {
    let backend: MockBackend;
    let service: UserService;
    let response: Response;

    beforeEach(async(() => {    
      TestBed.configureTestingModule({
        imports: [HttpModule],
        providers: [
          MockBackend,
          { provide: XHRBackend, useClass: MockBackend },

          UserService
        ]
      });
    }));

    beforeEach(inject([Http, XHRBackend], (http: Http, be: MockBackend) => {
      backend = be;
      service = new UserService(http);
      let options = new ResponseOptions({status: 500, body: 'API Error'});
      response = new Response(options);
    }));

    it('should handle an API error on getListUsers()', async(inject([], () => {
        backend.connections.subscribe((c: MockConnection) => {
          c.mockRespond(response);
        });

        expect(() => service.getListUsers()).toThrowError();
      }))
    );

  });

使用此测试用例,测试失败但没有更多信息:

  

抛出错误的预期函数。

我甚至尝试使用订阅来检测某些内容:

it('should handle an API error on getListUsers()', async(inject([], () => {
    backend.connections.subscribe((c: MockConnection) => {
      c.mockRespond(response);
    });

    spyOn(console, 'error');

    service.getListUsers()
      .subscribe(
      res => {},
      err => { 
        console.error(err)
      });

    expect(console.error).toHaveBeenCalled();
  }))
);

这里我可以看到控制台中抛出的错误,但是从不触发console.error。

所以,也许我的测试用例不合适。

1 个答案:

答案 0 :(得分:1)

该断言帮助程序不起作用,因为错误被包装并通过Observable的错误通知通道传播。

为此,您需要订阅observable并相应地断言

service.getListActivities().subscribe(
  () => test.failure('expected an error but observable terminated successfully.'),

  () => test.success('observable threw an error as expected.')
);

该示例被概括为您调用的特定帮助程序将取决于所使用的测试框架。