我想测试一个Angular 2组件内部的方法,该组件订阅了从服务中的方法返回的observable.以下是摘要中服务方法的代码:
public create(user: User): Observable<any> { return this.http.post(this._api.create,JSON.stringify(user),{ headers: this.apiConfig.getApiHeaders() }).map((res: Response) => res.json()); }
单元测试这个方法很容易,因为它返回一个observable,所以我可以订阅它.但是我想测试已经订阅了这个的组件中的方法:
public onSubmit(user: User): void { this._authentication.create(user).subscribe((token) => { localStorage.setItem('token',token); this.router.navigate(['/Home']); }); }
到目前为止我的规格是什么,但是当我试图窥探localStorage.setItem时,它会回来,因为没有被调用.我的理解是它可能会检查它是否在实际被调用之前被调用.
it('Should login a user and on success store a token in localStorage',injectAsync([TestComponentBuilder],(tcb) => { return tcb.createAsync(Login).then((fixture) => { let instance = fixture.debugElement.componentInstance; localStorage.clear(); spyOn(localStorage,'setItem'); instance.onSubmit({userId: 'some@email.com',password: 'password',siteName: 'sample'}); expect(localStorage.setItem).toHaveBeenCalled(); }); }) );
我想知道我是否需要模拟this._authentication.create方法来返回一个带有模拟响应的新observable?
经过更多的研究,一些文章表明我确实需要模拟服务并返回一个同步运行以解决问题的Observable.of(),复制下面的代码.然而,这仍然不起作用,我一直在努力这一天,我不觉得这应该是那么难,任何帮助赞赏.
class MockAuthentication extends Authentication { public create(user: Object): Observable<any> { return Observable.of({'test': 'test'}); } }
好的,所以这一天大部分时间都花了我,但我终于破解了它.而不是使用injectAsync和TestComponentBuilder来设置规范我只需要像使用服务一样使用注入和注入组件.这看起来很好,因为我不需要在视图中测试任何事件.
下面是确实有效的最终规范:
it('Should set token in localStorage,set the new user,and navigate to home page on succesful login',inject([Login],(login) => { login.router.config([ { path: '/',name: 'Home',component: Home }]); spyOn(localStorage,'setItem'); spyOn(login._currentUser,'set'); spyOn(login.router,'navigate'); login.onSubmit({ userId: 'some@email.com',siteName: 'sample' }); expect(localStorage.setItem).toHaveBeenCalledWith('token','newToken'); expect(login._currentUser.set).toHaveBeenCalledWith({ 'test': 'one' }); expect(login.router.navigate).toHaveBeenCalledWith(['/Home']); }));
希望这可能会帮助将来的某个人.