【问题标题】:Angular 2 unit test http.get undefinedAngular 2 单元测试 http.get undefined
【发布时间】:2016-10-15 04:26:01
【问题描述】:

我正在尝试使用 MockBackend 为异步 http 服务编写 angular 2 单元测试,但出现 http.get undefined 错误。这是我的代码:

Http服务:

import { Injectable } from '@angular/core';
import { Http,Headers,RequestOptions,Response } from '@angular/http';
import 'rxjs/add/operator/map';
import 'rxjs/Rx';

@Injectable()
export class HttpService {


    constructor(private _http: Http) {}

    /**
     *  Http request will time out if not received response within 20 sec
     * 
     * @param url
     * @returns {Observable<R>}
     */
    getData(url : string) {
        return this._http.get(url)
            .timeout(20000, new Error('delay exceeded'))
            .map(response => response.json());
    }

}

我正在为其编写单元测试的自定义组件方法:

 private loadDetails(input : string){
        this._httpService.getData("/api/test"+ input)
            .subscribe(
                data => {this.user = data,
                         // Some more logic in here based on data     
                },
                error =>  { console.log( error);}
            );
    }

单元测试:

import { HttpService } from "../shared/services/http.service";
import {
    async,
    inject,
    fakeAsync,
    TestBed
} from '@angular/core/testing';

import {
Http,
    BaseRequestOptions,
    Response,
    BaseResponseOptions,
    ResponseOptions
} from '@angular/http';

import { HttpModule } from '@angular/http';

import {
    MockBackend,
    MockConnection
} from '@angular/http/testing';
import { Observable } from 'rxjs/Rx';

import { TestingComponent } from './testing.component';

const mockHttpProvider = {
    deps: [ MockBackend, BaseRequestOptions ],
    useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
        return new Http(backend, defaultOptions);
    }
}

describe('testingComponent', () => {

    let fixture,testingComponent;

    // provide our implementations or mocks to the dependency injector
    beforeEach(() => {

        TestBed.configureTestingModule({
            declarations: [
                CustomComponent
            ],
            providers: [
                HttpService,
                MockBackend,
                BaseRequestOptions,
                {provide: Http, useValue: mockHttpProvider}
            ]
        });

        fixture = TestBed.createComponent(PortfolioComponent);
        testingComponent = fixture.debugElement.componentInstance;
    });


    it('should call loadDetails to load user details',  inject(
        [IPIQHttpService, MockBackend],
        fakeAsync((service: HttpService, backend: MockBackend) => {
            backend.connections.subscribe((connection: MockConnection) => {

                let mockResponseBody= {
                    id: '123',
                    title: 'test',
                    empno: '456'
                };

                let response = new ResponseOptions({body: JSON.stringify(mockResponseBody)});
                connection.mockRespond(new Response(response));
            });
            testingComponent.loadUserDetails('123');
            expect(testingComponent.user.empno).toEqual('456');
        })));


});

当我调用 testingComponent.loadUserDetails('123') 来调用 http 服务时,我得到未定义的 http.get 方法。

知道我在这里做错了什么吗?

【问题讨论】:

    标签: angular angular2-services


    【解决方案1】:
    const mockHttpProvider = { 
        provide: Http,
        deps: [ MockBackend, BaseRequestOptions ],
        useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
            return new Http(backend, defaultOptions);
        }
    }
    
      TestBed.configureTestingModule({
            imports: [HttpModule], // <<<=== added
            declarations: [
                CustomComponent
            ],
            providers: [
                HttpService,
                MockBackend,
                BaseRequestOptions,
                mockHttpProvider
            ]
        });
    

    【讨论】:

    • 我添加了 HttpModule 导入,但仍然出现同样的错误:TypeError: this._http.get is not a function
    • 您能否在添加测试代码的位置创建一个新问题?
    • 抱歉,不确定您的测试代码是什么意思?我已经在这里发布了我的测试代码。
    • 不知道。我确定它昨天不在那里。也许我的视力受损;-)。您是否尝试将console.log(_http) 添加到HttpService。通常当注入失败时它会抛出,但在你的情况下,应用程序似乎会继续,这很奇怪。
    • 什么是IPIQHttpService,从哪里调用loadDetails
    【解决方案2】:

    终于成功了。以下是我所做的更改:

    1. 按照@Günter Zöchbauer 在上一篇文章中的建议,导入了 HttpModule 并改变了我使用 mockHttpProvider 的方式:
    const mockHttpProvider =  
    { 
    provide: Http,
     deps: [ MockBackend, BaseRequestOptions ], 
    useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => 
    { return new Http(backend, defaultOptions); } 
    }
    
     TestBed.configureTestingModule({
            imports: [HttpModule], // <<<=== added
            declarations: [
                CustomComponent
            ],
            providers: [
                HttpService,
                MockBackend,
                BaseRequestOptions,
                mockHttpProvider
            ]
        });
    
    1. 更改了我的单元测试并删除了 fakeAsync:
    it('should call loadDetails to load user details', inject([HttpService, MockBackend, Http], (_httpService, backend, http) => {
            backend.connections.subscribe(connection => {
                let mockResponseBody= {
                     id: '123',
                     title: 'test',
                     empno: '456'
                };
                let response = new ResponseOptions({body: JSON.stringify(mockResponseBody)});
                connection.mockRespond(new Response(response));
            });
            testingComponent.loadDetails('123');
            expect(testingComponent.user.empno).toEqual('456');
        }));
    

    【讨论】:

      猜你喜欢
      • 2016-12-29
      • 2018-04-11
      • 2017-06-28
      • 1970-01-01
      • 2017-06-03
      • 1970-01-01
      • 1970-01-01
      • 2017-10-10
      相关资源
      最近更新 更多