web-dev-qa-db-ja.com

オブザーバブルにサブスクライブされているメソッドのテスト-Angular 2

サービス内のメソッドから返されるオブザーバブルにサブスクライブされている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をspyOnしようとすると、呼び出されていないものとして返されます。私の理解では、実際に呼び出される前に、呼び出されたかどうかを確認している可能性があります。

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: '[email protected]', 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'});
  }
}
8
HomeBrew

さて、それは私にほとんど一日かかったが、私はついにそれを割った。 injectAsyncとTestComponentBuilderを使用して仕様を設定する代わりに、サービスを実行するのと同じように、injectを使用してコンポーネントを注入する必要があります。イベントのようにビューで何もテストする必要がないので、これは問題ないようです。

動作する最終仕様は次のとおりです。

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

これが将来誰かを助けるかもしれないことを願っています。

3
HomeBrew

コンポーネントにモックRouterインスタンスを挿入し、モックRouternavigate(['/Home'])が呼び出された後、localStorage.setItem(...)かどうかを確認すると思います。と呼ばれていました。

1