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

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

问题描述

我有一个拦截器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();
        }))
    );
});

刷新响应时,我不知道如何刷新错误响应,以便方法<将在我的拦截器中调用code> 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.

推荐答案

expectOne 方法 HttpTestingController 类返回一个 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


两个成功回复不成功。

both successful and unsuccessful responses.

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

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: 404, 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);

注意:在撰写此评论时, statusText mockErrorResponse 中是必需的。相关信息可以在这里找到。

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天全站免登陆