如何对这个从管道可观察到的错误捕获的 Angular 打字稿 Http 错误拦截器进行单元测试?
Posted
技术标签:
【中文标题】如何对这个从管道可观察到的错误捕获的 Angular 打字稿 Http 错误拦截器进行单元测试?【英文标题】:How to unit test this Angular typescript Http Error Interceptor that catches errors from a piped observable? 【发布时间】:2019-05-10 01:37:52 【问题描述】:我正在进行一项实验,通过测试其他人的代码(例如自动化单元和端到端测试)来学习角度和打字稿。在我对其进行测试后,我计划将其重新用于我正在为大学教室进行的宠物项目。
我从这里开始对代码进行至少一半的单元测试:http://jasonwatmore.com/post/2018/05/16/angular-6-user-registration-and-login-example-tutorial
一段时间以来,我一直在尝试对以下代码进行单元测试,但到目前为止,我从自己的想法或互联网上的想法中尝试的一切都没有成功:
import HttpInterceptor, HttpRequest, HttpHandler, HttpEvent from "@angular/common/http";
import AuthenticationService from "src/app/authenticationService/AuthenticationService";
import Observable, throwError from "rxjs";
import catchError from "rxjs/operators";
import Injectable from "@angular/core";
@Injectable()
export class ErrorInterceptor implements HttpInterceptor
constructor(private authenticationService: AuthenticationService)
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>
console.log('before error handle')
return next.handle(request).pipe(catchError(err =>
console.log('in error handle')
if (err.status === 401)
// auto logout if 401 response returned from api
this.authenticationService.logout();
location.reload(true);
const error = err.error.message || err.statusText;
return throwError(error);
))
以下测试代码和几个变体未能成功让“错误句柄”消息显示在控制台日志中:
import ErrorInterceptor from "./ErrorInterceptor";
import of, throwError, defer from "rxjs";
describe('ErrorInterceptor', () =>
let errorInterceptor;
let authenticationServiceSpy;
beforeEach(() =>
authenticationServiceSpy = jasmine.createSpyObj('AuthenticationService', ['logout']);
errorInterceptor = new ErrorInterceptor(authenticationServiceSpy);
)
it('should create', () =>
expect(errorInterceptor).toBeTruthy();
)
describe('intercept', () =>
let httpRequestSpy;
let httpHandlerSpy;
const error = status: 401, statusText: 'error';
it('should auto logout if 401 response returned from api', () =>
//arrange
httpRequestSpy = jasmine.createSpyObj('HttpRequest', ['doesNotMatter']);
httpHandlerSpy = jasmine.createSpyObj('HttpHandler', ['handle']);
httpHandlerSpy.handle.and.returnValue(
pipe: () =>
return fakeAsyncResponseWithError();
);
//act
errorInterceptor.intercept(httpRequestSpy, httpHandlerSpy);
//assert
//TBD
function fakeAsyncResponseWithError<T>(data: T)
return defer(() => throwError(error));
)
)
)
【问题讨论】:
【参考方案1】:这里有几个问题。
首先,httpHandlerSpy.handle()
的返回值必须是 Observable,因为上面已经有管道运算符,然后 HttpInterceptor 代码可以根据需要通过管道将其传递给 catchError。
其次,HttpInterceptor 返回一个 Observable,要“执行”它,需要订阅它。
我整理了一个Stackblitz 来展示我将如何处理这个问题。
来自 Stackblitz,这是规范(it
函数):
it('should auto logout if 401 response returned from api', () =>
//arrange
httpRequestSpy = jasmine.createSpyObj('HttpRequest', ['doesNotMatter']);
httpHandlerSpy = jasmine.createSpyObj('HttpHandler', ['handle']);
httpHandlerSpy.handle.and.returnValue(throwError(
error:
message: 'test-error'
));
//act
errorInterceptor.intercept(httpRequestSpy, httpHandlerSpy)
.subscribe(
result => console.log('good', result),
err =>
console.log('error', err);
expect(err).toEqual('test-error');
);
//assert
)
我希望这会有所帮助。
【讨论】:
真的很感激。谢谢!它不仅彻底简洁地回答了我的问题,而且还通过一些可运行的演示代码在此过程中教授了一些东西。 这个答案对我也有帮助。谢谢:-) @dmcgrandle,你能回答这个问题吗:***.com/questions/63555118/… 我有 2 个私有方法。以上是关于如何对这个从管道可观察到的错误捕获的 Angular 打字稿 Http 错误拦截器进行单元测试?的主要内容,如果未能解决你的问题,请参考以下文章