如何在测试中模拟 Angular 4.3 httpClient 的错误响应 [英] How to mock Angular 4.3 httpClient an error response in testing

查看:23
本文介绍了如何在测试中模拟 Angular 4.3 httpClient 的错误响应的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个下面的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 控制错误消息.

Now I am trying to mock the http.get to throw the error, so that method handleError consoles the error message.

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

Below is my approach to the test case 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.文档没有任何关于我的情况的例子.任何帮助或建议表示赞赏.

When flushing the response, I am not sure how to flush a error response, so that the method handleError will be called in my interceptor and that eventually calls console.error. Documentation doesn't have any example to my situation. Any help or suggestion is appreciated.

推荐答案

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

The expectOne method in HttpTestingController class returns a TestRequest object. This TestRequest class has a flush method which can be used to deliver

成功和不成功的响应.

我们可以通过返回一个正文以及一些额外的响应头(如果有)来解决请求.相关信息可以在此处找到.

We can resolve the request by returning a body along with some additional response headers (if any). Relevant info can be found here.

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

Now, coming back to the point how you can do this. You can customize the below code snippet as per your use case.

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);

注意:在撰写此评论时,mockErrorResponse 中需要 statusText.相关信息可以在此处找到.

NOTE: At the time of writing this comment, statusText is required in mockErrorResponse. Related info can be found here.

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

P.S.: The error method of TestRequest class can be used to simulate network error in our test case, as it expects an instance of Error. The following code snippet shows that.

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

这篇关于如何在测试中模拟 Angular 4.3 httpClient 的错误响应的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆