所有单元测试都与服务引发错误的单元测试分开(由于HTTP状态代码错误).我可以通过退出response.ok告诉我.从我所读到的,这与单元测试没有异步执行有关,因此,不等待错误响应.但是,我不知道为什么会出现这种情况,因为我在beforeEach方法中使用了async()实用程序函数.
API服务
get(endpoint: string,authenticated: boolean = false): Observable<any> { endpoint = this.formatEndpoint(endpoint); return this.getHttp(authenticated) // Returns @angular/http or a wrapper for handling auth headers .get(endpoint) .map(res => this.extractData(res)) .catch(err => this.handleError(err)); // Not in guide but should work as per docs } private extractData(res: Response): any { let body: any = res.json(); return body || { }; } private handleError(error: Response | any): Observable<any> { // TODO: Use a remote logging infrastructure // TODO: User error notifications let errMsg: string; if (error instanceof Response) { const body: any = error.json() || ''; const err: string = body.error || JSON.stringify(body); errMsg = `${error.status} - ${error.statusText || ''}${err}`; } else { errMsg = error.message ? error.message : error.toString(); } console.error(errMsg); return Observable.throw(errMsg); }
错误单元测试
// Imports describe('Service: APIService',() => { let backend: MockBackend; let service: APIService; beforeEach(async(() => { TestBed.configureTestingModule({ providers: [ BaseRequestOptions,MockBackend,APIService,{ deps: [ MockBackend,BaseRequestOptions ],provide: Http,useFactory: (backend: XHRBackend,defaultOptions: BaseRequestOptions) => { return new Http(backend,defaultOptions); } },{provide: AuthHttp,useFactory: (http: Http,options: BaseRequestOptions) => { return new AuthHttp(new AuthConfig({}),http,options); },deps: [Http,BaseRequestOptions] } ] }); const testbed: any = getTestBed(); backend = testbed.get(MockBackend); service = testbed.get(APIService); })); /** * Utility function to setup the mock connection with the required options * @param backend * @param options */ function setupConnections(backend: MockBackend,options: any): any { backend.connections.subscribe((connection: MockConnection) => { const responSEOptions: any = new ResponSEOptions(options); const response: any = new Response(responSEOptions); console.log(response.ok); // Will return false during the error unit test and true in others (if spyOn log is commented). connection.mockRespond(response); }); } it('should log an error to the console on error',() => { setupConnections(backend,{ body: { error: `Some strange error` },status: 400 }); spyOn(console,'error'); spyOn(console,'log'); service.get('/bad').subscribe(null,e => { // None of this code block is executed. expect(console.error).toHaveBeenCalledWith("400 - Some strange error"); console.log("Make sure an error has been thrown"); }); expect(console.log).toHaveBeenCalledWith("Make sure an error has been thrown."); // Fails });
更新1
当我检查第一个回调时,response.ok未定义.这让我相信setupConnections实用程序有问题.
it('should log an error to the console on error',async(() => { setupConnections(backend,'error'); //spyOn(console,'log'); service.get('/bad').subscribe(res => { console.log(res); // Object{error: 'Some strange error'} console.log(res.ok); // undefined },e => { expect(console.error).toHaveBeenCalledWith("400 - Some strange error"); console.log("Make sure an error has been thrown"); }); expect(console.log).toHaveBeenCalledWith("Make sure an error has been thrown."); }));
更新2
如果不是在get方法中捕获错误而是在map中明确地执行它,那么仍然有相同的问题.
get(endpoint: string,authenticated: boolean = false): Observable<any> { endpoint = this.formatEndpoint(endpoint); return this.getHttp(authenticated).get(endpoint) .map(res => { if (res.ok) return this.extractData(res); return this.handleError(res); }) .catch(this.handleError); }
更新3
经过一些讨论this issue提交