Angular 6-Jasmine-模拟httpClient获取映射和错误流

时间:2018-11-20 00:20:44

标签: unit-testing jasmine mocking angular6 angular-httpclient

我是Angular测试的新手,正在尝试弄清楚如何编写一个模拟HttpClient.get()函数错误响应的测试。基本上,我的服务在其pipe()中同时具有map()和catchError(),我想同时行使这两种流程。这是我到目前为止的内容:

my.service.ts:

getItems(): Observable<ItemViewModels[]> {
    return 
        this.httpClient.get<any>(this.getItemsUrl)
        .pipe(
            map(json => {
                return json.map(itemJson => this.getVmFromItemJson(itemJson));
            }),
            catchError(() => {
                // Log stuff here...
                return of(null);
            })
        );
}

my.service.spec.ts:

it('should catch error and return null if API returns error', () => {
    spyOn(service.httpClient, 'get').and.returnValue(new Observable()); // Mock error here
    service.getItems().subscribe($items => expect($items).toBe(null));
});

it('should return valid view model array if API returns a valid json', () => {
    const mockResponse = [
        new SideNavItemViewModel(1),
        new SideNavItemViewModel(2),
        new SideNavItemViewModel(3)
    ];

    spyOn(service.httpClient, 'get').and.returnValue(of(JSON.stringify(mockResponse)));
    service.getSidenavViewModel().subscribe(x => expect(x).toBe(mockResponse));
});

因此,实际的问题是,我模拟供httpClient返回以在单元测试中返回的可观察对象似乎未进入.pipe()函数,这意味着我的测试无法正常工作:(

有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

您是否尝试过将服务注入测试?我也尝试测试订阅api调用的功能,而不是创建另一个订阅:

错误:

it('should display error when server error occurs',
    inject([HttpTestingController, AService],
        (httpMock: HttpTestingController, svc: MyService) => {

        svc.getItems(); // has the subscribe in it

        const callingURL = svc['API']; // your api call eg. data/items

        httpMock.expectOne((req: HttpRequest < any > ) => req.url.indexOf(callingURL) !== -1)
        .error(new ErrorEvent('Customer Error', {
                error: 500
            }), {
            status: 500,
            statusText: 'Internal Server Error'
        });

        httpMock.verify();

        expect(component.svc.Jobs).toBeUndefined();

        fixture.detectChanges();

        // UI check here

    }));

数据测试

it('should display the correct amount of data elements',
    inject([HttpTestingController, AService],
        (httpMock: HttpTestingController, svc: MyService) => {

        svc.getItems();  // has the subscribe in it

        const callingURL = svc['API']; // your api call eg. data/items

        const mockReq = httpMock.expectOne((req: HttpRequest < any > ) => req.url.indexOf(callingURL) !== -1);

        mockReq.flush(mockData);

        httpMock.verify();

        expect(component.svc.data.length).toBe(mockData.length);

        fixture.detectChanges();
        // UI check here

    }));

所以基本上这些功能:

  • 致电获取并订阅
  • 检查您的api网址是否包含在http调用中
  • 删除响应-您传递数据-'mockData'
  • mockReq.flush(mockData);将触发通话
  • httpMock.verify();将检查网址和其他内容
  • 现在可以测试服务数据了-如果您在其中设置了任何内容
  • fixture.detectChanges(); -那么这将允许测试ui组件

我更喜欢这种方式,因为您可以将逻辑和测试分开。