我的血压低于interceptor auth-interceptor.service.ts

import {Injectable, Injector} from '@angular/core';
import {HttpErrorResponse, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from '@angular/common/http';
import {Observable} from 'rxjs/Observable';
import {Cookie} from './cookie.service';
import {Router} from '@angular/router';
import {UserService} from './user.service';
import {ToasterService} from '../toaster/toaster.service';
import 'rxjs/add/operator/catch';
import 'rxjs/add/observable/throw';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    constructor(private injector: Injector) {}

    private handleError(err: HttpErrorResponse): Observable<any> {
        let errorMsg;
        if (err.error instanceof Error) {
            // A client-side or network error occurred. Handle it accordingly.
            errorMsg = `An error occurred: ${err.error.message}`;
        } else {
            // The backend returned an unsuccessful response code.
            // The response body may contain clues as to what went wrong,
            errorMsg = `Backend returned code ${err.status}, body was: ${err.error}`;
        }
        if (err.status === 401 || err.status === 403) {
            this.injector.get(UserService).purgeAuth();
            this.injector.get(ToasterService).showError(`Unauthorized`, errorMsg);
            this.injector.get(Router).navigateByUrl(`/login`);
        }
        console.error(errorMsg);
        return Observable.throw(errorMsg);
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // Clone the request to add the new header.
        const authReq = req.clone({headers: req.headers.set(Cookie.tokenKey, Cookie.getToken())});
        // Pass on the cloned request instead of the original request.
        return next.handle(authReq).catch(err => this.handleError(err));
    }
}

现在我试图模拟http.get来抛出错误,这样方法handleError就可以处理错误消息.

下面是我对测试用例auth-interceptor.service.specs.ts的处理方法

import {async, inject, TestBed} from '@angular/core/testing';

import {AuthInterceptor} from './auth-interceptor.service';
import {ApiService} from './api.service';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {environment} from '../../../environments/environment';

describe(`AuthInterceptor`, () => {
    const somePath = `/somePath`;

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

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


    it(`should log an error to the console on error on get()`, async(inject([ApiService, HttpTestingController],
        (apiService: ApiService, httpMock: HttpTestingController) => {
            spyOn(console, 'error');
            apiService.get(somePath).subscribe((res) => {
                console.log(`in success:`, res);
            }, (error) => {
                console.log(`in error:`, error);
            });

            const req = httpMock.expectOne(`${environment.apiUri}${somePath}`);
            req.flush({
                type: 'ERROR',
                status: 404,
                body: JSON.stringify({color: `blue`})
            });
            expect(console.error).toHaveBeenCalled();
        }))
    );
});

在刷新响应时,我不确定如何刷新错误响应,以便在我的拦截器中调用方法handleError,最终调用console.error.文档中没有任何例子可以说明我的情况.任何帮助或建议都将不胜感激.

推荐答案

HttpTestingController类中的expectOne方法返回TestRequest对象.这个TestRequest类有一个flush方法,可以用来

成功和失败的回答.

我们可以通过返回一个正文和一些额外的响应头(如果有的话)来解决请求.相关信息请点击here.

现在,回到你如何做到这一点.您可以根据自己的用例自定义下面的代码段.

http = TestBed.get(HttpTestingController);
let response: any;
let errResponse: any;
const mockErrorResponse = { status: 400, statusText: 'Bad Request' };
const data = 'Invalid request parameters';
apiService.get(somePath).subscribe(res => response = res, err => errResponse = err);
http.expectOne('url/being/monitored').flush(data, mockErrorResponse);
expect(errResponse).toBe(data);

NOTE:在 compose 本 comments 时,mockErrorResponse中需要statusText.相关信息请点击here.

P.S.:TestRequest类的error方法可以用于在我们的测试用例中模拟网络错误,因为它需要一个错误实例.下面的代码片段显示了这一点.

http.expectOne(someUrl).error(new ErrorEvent('network error'));

Typescript相关问答推荐

与Prettify助手类型中的对象相交?

Typescript问题和缩减器状态不会在单击时添加用途.属性'状态和调度'不存在于userContextType类型上'|null'

如何使打包和拆包功能通用?

类型脚本`Return;`vs`Return unfined;`

在嵌套属性中使用Required

诡异的文字类型--S为物语的关键

尽管对象的类型已声明,但未解析的变量<;变量

声明文件中的类型继承

在React中定义props 的不同方式.FunctionalComponent

->;Boolean类型的键不能分配给类型Never

带投掷的收窄类型

如何为特定参数定义子路由?

如何键入并类型的函数&S各属性

TaskListProps[]类型不可分配给TaskListProps类型

在TypeScript中,如何通过一系列过滤器缩小类型?

如何提取具有索引签名的类型中定义的键

递归JSON类型脚本不接受 node 值中的变量

如何在TypeScript中声明逆变函数成员?

如何让Record中的每个值都有独立的类型?

我应该使用服务方法(依赖于可观察的)在组件中进行计算吗?