jasmine - 测试订阅可观察对象的方法 - Angular 2

标签 jasmine angular rxjs

我想测试 Angular 2 组件内部的一个方法,该组件订阅了从服务中的方法返回的可观察对象。以下是服务方法的代码摘要:

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());
  }

很容易对该方法进行单元测试,因为它返回一个可观察对象,所以我可以订阅它。但是我想测试已经订阅的组件中的方法:

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.of() 来解决问题,我将复制下面的代码。然而,这仍然行不通,我一天大部分时间都在做这件事,我觉得这不应该那么难,感谢任何帮助。

class MockAuthentication extends Authentication {
  public create(user: Object): Observable<any> {
    return Observable.of({'test': 'test'});
  }
}

最佳答案

好吧,这花了我一天的大部分时间,但我终于破解了它。无需使用 injectAsync 和 TestComponentBuilder 来设置规范,我只需要像执行服务一样使用注入(inject)和注入(inject)组件。这看起来不错,因为我不需要像事件一样在 View 中测试任何东西。

这是有效的最终规范:

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', password: 'password', siteName: 'sample' });
    expect(localStorage.setItem).toHaveBeenCalledWith('token', 'newToken');
    expect(login._currentUser.set).toHaveBeenCalledWith({ 'test': 'one' });
    expect(login.router.navigate).toHaveBeenCalledWith(['/Home']);
}));

希望这对将来的人有所帮助。

关于jasmine - 测试订阅可观察对象的方法 - Angular 2,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35658948/

相关文章:

javascript - 使用 Angular 和 rxjs 导入 ES6 模块

javascript - 对触发可观察量上的某些可观察量执行操作 - RxJS

javascript - Cycle.js 应用程序未捕获的类型错误

javascript - Jasmine 测试 : Expected undefined to equal Object

Angular 6 在两个不相关的组件之间传递数据

backbone.js - 使用 Jasmine 单独测试 Marionette 模块

angular - 如何在 Angular 中使用 ngFor 同时迭代两个数组?

angular - 从 api 响应创建可观察数组

google-chrome - Karma - Chrome 失败 2 次(无法启动)。放弃

javascript - 无法使用vue和moment将参数传递给 Jasmine 中的按钮方法