【问题标题】:Angular 6 - Jasmine - mock httpClient get map and error flowsAngular 6 - Jasmine - 模拟 httpClient 获取地图和错误流
【发布时间】:2018-11-20 00:20:43
【问题描述】:

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

我的.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() 函数,这意味着我的测试不起作用:(

有什么想法吗?

谢谢!

【问题讨论】:

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


    【解决方案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 url 是否包含在 http 调用中
    • 模拟响应 - 你传入数据 - 'mockData'
    • mockReq.flush(mockData);会触发通话
    • httpMock.verify();将检查网址和其他内容
    • 现在可以测试服务数据 - 如果您订阅其中设置任何内容
    • fixture.detectChanges(); - 然后这将允许测试 ui 组件

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

    【讨论】:

      猜你喜欢
      • 2022-11-02
      • 1970-01-01
      • 2019-04-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-08-08
      • 1970-01-01
      相关资源
      最近更新 更多