Angular 7-在单元测试中捕获HttpErrorResponse



我目前正在学习Angular 7(没有使用任何以前的版本(,在为服务编写单元测试时遇到了一些无法解决的问题。

我有一个服务,它从REST获取JSON并将其解析为一个类。参考Angular Docs,我使用HttpClientSpy编写了一个测试来模拟404错误。

发生的情况:测试失败,并显示错误消息:"预期数据。forEach不是包含‘404’的函数">

因此,服务获取HttpErrorResponse作为输入,但试图将其解析为map函数中的常规响应。如果失败,将调用catchError,并且data.forEach不是函数,则抛出Error。

预期行为:我预期map((不会被执行,它应该直接跳到catchError函数中。

我是如何修复的(目前(:将以下代码行添加到服务的映射函数中可以使测试工作。

if (data instanceof HttpErrorResponse)
throw new HttpErrorResponse(data);

测试:

it('should throw an error when 404', () => {
const errorResponse = new HttpErrorResponse({
error: '404 error',
status: 404, statusText: 'Not Found'
});
httpClientSpy.get.and.returnValue(of(errorResponse));
service.getComments().subscribe(
fail,
error => expect(error.message).toContain('404')
);
});

服务:

getComments(): Observable<CommentList> {
return this.http
.get('https://jsonplaceholder.typicode.com/comments')
.pipe(
map((data: Array<any>) => {
let t: Array<Comment> = [];
data.forEach(comment => {
if(!('id' in comment) || !('body' in comment) || !('email' in comment) || !('name' in comment))
throw new Error("Could not cast Object returned from REST into comment");
t.push(<Comment>{
id: comment.id,
body: comment.body,
author: comment.email,
title: comment.name,
});
});
return new CommentList(t);
}),
catchError((err: HttpErrorResponse) => {
return throwError(err);
})
);
}

我是不是搞错了?我认为预期的行为是我应该经历的,至少这是我解释Angular文档的方式。

这是一个迟来的答案,方法略有不同,但这也有效。

it('should show modal if failed', inject([Router], (mockRouter: Router) => {
const errorResponse = new HttpErrorResponse({
error: { code: `some code`, message: `some message.` },
status: 400,
statusText: 'Bad Request',
});
spyOn(someService, 'methodFromService').and.returnValue(throwError(errorResponse));
expect...
expect...
expect...
}));

回答较晚,但可能会帮助面临类似问题的人。

根本原因

错误消息:";预期的数据.forEach不是包含"404"的函数;是因为测试用例中的of运算符:

httpClientSpy.get.and.returnValue(of(errorResponse));

of运算符返回一个可观察到的值,该值会发出参数。

当您想要返回数据时,这很有用,但当您想要引发404错误时,这就不有用了。

为了让间谍提出错误,响应应该拒绝而不是解决。

解决方案1

此解决方案使用deferRxJS运算符以及您在示例中使用的jasmine.createSpyObj方法。

import { TestBed } from '@angular/core/testing';
import { HttpErrorResponse } from '@angular/common/http';
import { defer } from 'rxjs';
import { CommentsService } from './comments.service';
// Create async observable error that errors
//  after a JS engine turn
export function asyncError<T>(errorObject: any) {
return defer(() => Promise.reject(errorObject));
}
describe('CommentsService', () => {
let httpClientSpy: { get: jasmine.Spy };
let service: CommentsService;
beforeEach(() => {
httpClientSpy = jasmine.createSpyObj('HttpClient', ['get']);
service = new CommentsService(httpClientSpy as any);
});
it('should throw an error when 404', () => {
const errorResponse = new HttpErrorResponse({
error: '404 error',
status: 404,
statusText: 'Not Found'
});
httpClientSpy.get.and.returnValue(asyncError(errorResponse));
service.getComments().subscribe(
data => fail('Should have failed with 404 error'),
(error: HttpErrorResponse) => {
expect(error.status).toEqual(404);
expect(error.error).toContain('404 error');
});
});
});

解决方案2

最好使用angular HttpClientTestingModule来测试HttpClient的使用情况。以下示例显示了使用HttpClientTestingModule进行的相同测试。

import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpErrorResponse } from '@angular/common/http';
import { CommentsService } from './comments.service';
describe('CommentsService test using HttpClientTestingModule', () => {
let httpTestingController: HttpTestingController;
let service: CommentsService;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ HttpClientTestingModule ]
});
httpTestingController = TestBed.get(HttpTestingController);
service = TestBed.get(CommentsService);
});
it('throws 404 error', () => {
service.getComments().subscribe(
data => fail('Should have failed with 404 error'),
(error: HttpErrorResponse) => {
expect(error.status).toEqual(404);
expect(error.error).toContain('404 error');
}
);
const req = httpTestingController.expectOne('https://jsonplaceholder.typicode.com/comments');
// Respond with mock error
req.flush('404 error', { status: 404, statusText: 'Not Found' });
});
});

有角度的HTTP测试文档解释了这种方法。

注意:这些示例是使用Angular v8进行测试的。

相关内容

  • 没有找到相关文章

最新更新