单元测试 – Angular 2单元测试可观察错误(HTTP)
我正在尝试为我的API服务编写单元测试,但在捕获HTTP错误时遇到一些问题.我跟随这个
guide以及Angular2文档,因为指南在某些小区域(稍微)过时了.
所有单元测试都与服务引发错误的单元测试分开(由于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提交
您需要在测试用例(它)中使用它.异步的作用是创建一个测试区域,在完成测试(或测试区域,例如beforeEach)之前等待所有异步任务完成. 因此,beforeEach中的async只是等待异步任务在退出之前在方法中完成.但它也需要同样的东西. it('should log an error to the console on error',async(() => { })) UPDATE 除了丢失的异步之外, mockRespond(res: Response) { if (this.readyState === ReadyState.Done || this.readyState === ReadyState.Cancelled) { throw new Error('Connection has already been resolved'); } this.readyState = ReadyState.Done; this.response.next(res); this.response.complete(); } 他们有一个 mockError(err?: Error) { // Matches ResourceLoader semantics this.readyState = ReadyState.Done; this.response.error(err); } 但这不会调用允许您传递响应.这与真正的 response.ok = isSuccess(status); if (response.ok) { responSEObserver.next(response); // TODO(gdi2290): defer complete if array buffer until done responSEObserver.complete(); return; } responSEObserver.error(response); 对我来说听起来像个错误.你应该报告的事情.它们应该允许您在mockError中发送Response,或者在mockRespond中对它们在XHRConnection中执行相同的检查. 更新(通过OP)S??etupConnections() 当前解决方案 function setupConnections(backend: MockBackend,options: any): any { backend.connections.subscribe((connection: MockConnection) => { const responSEOptions: any = new ResponSEOptions(options); const response: any = new Response(responSEOptions); // Have to check the response status here and return the appropriate mock // See issue: https://github.com/angular/angular/issues/13690 if (responSEOptions.status >= 200 && responSEOptions.status <= 299) connection.mockRespond(response); else connection.mockError(response); }); } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |