2017-04-04 17 views
2

コンポーネントを単体テストしたい。私は@ ngrx/storeとrxjsを使用して、自分のコンポーネントを自分のコンポーネントから更新しています。これを行うために、私は店を購読し、購読を解除する。 私のユニットテストは、私が正しく私の店とそのイベントエミッタを模擬する方法を見つけることができないのです@ ngrx/storeを模倣する方法は?

TypeError: undefined is not an object (evaluating 'this.store.unsubscribe') in config/spec-bundle.js

で失敗しています。

app.component.ts:

ngOnDestroy() { 
    // unsubscribe the observable 
    this.userStore.unsubscribe(); 
    } 

app.component.spec.ts:

は、ここで次の行です

 export class MockStore extends Subject<fromRoot.State> implements Store <fromRoot.State> {} 
:私は店を模擬する方法

設定方法:

 TestBed.configureTestingModule({ 
     imports: [ 
      FormsModule, 
      ReactiveFormsModule, 
      StoreModule.provideStore(reducer) 
     ], 
     declarations: [LoginComponent], 
     providers: [ 
      BaseRequestOptions, 
      MockBackend, 
      { provide: AuthService, useValue: authServiceStub }, 
      { provide: LoginService, useValue: loginServiceStub }, 
      { provide: LoggerService, useValue: loggerServiceStub }, 
      { 
       provide: Http, useFactory: (backend: ConnectionBackend, 
        defaultOptions: BaseRequestOptions) => { 
        return new Http(backend, defaultOptions); 
       }, deps: [MockBackend, BaseRequestOptions] 
      }, 
      { provide: Router, useClass: MockRouter } 
     ] 
    }) 

詳細を知りたい場合は教えてください。前もって感謝します。

答えて

5

店舗を模擬する方法は複数あり、テストする方法に依存しています。私は私のテストで店を模擬すると

は、私は2つのことにしか興味だ:

  • 簡単にテストに関連性​​の状態を放出することができるという。そして
  • は、私は、彼らが他の場所でテストしているとして、減速をアップ配線には興味がないtest.the

時に店に派遣されているすべてのアクションを見ることができるので、これは私が何をすべきかです。

私はStoreSubject 2からインスタンスを作成するには、このような関数を使用します。

import { Action, Store } from "@ngrx/store"; 
import { Subject } from "rxjs/Subject"; 

export function mockStore<T>({ 
    actions = new Subject<Action>(), 
    states = new Subject<T>() 
}: { 
    actions?: Subject<Action>, 
    states?: Subject<T> 
}): Store<T> { 

    let result = states as any; 
    result.dispatch = (action: Action) => actions.next(action); 
    return result; 
} 

そしてbeforeEachに、私はStoreを作成し、それを追加しTestBedproviders

actions = new Subject<Action>(); 
states = new Subject<AppState>(); 
store = mockStore<AppState>({ actions, states }); 

TestBed.configureTestingModule({ 
    imports: [EffectsTestingModule], 
    providers: [ 
    { 
     provide: Store, 
     useValue: store 
    }, 
    ... 
    ] 
}); 

偽装されたStoreがコンポーネントやエフェクトなどに注入されているため、テスト中に特定の状態を出すのは簡単です - states件名を使用しています。actions件の件名に登録することで、予想どおりの行動が送信されたかどうかを確認するのは簡単です。

エラーについてはStoreunsubscribeを呼び出してはいけません。ストアに登録するときに返されるSubscriptionオブジェクトで呼び出す必要があります(他の回答に記載されています)。

+0

あなたの答えをありがとう。あなたがやっているやり方でやってみましたが、まだエラーがありました...私が他の答えで言ったように、私はすでにサブスクリプションオブジェクトに対して自分のサブスクリプションを呼び出しています。 – Megan

1

問題はあなたの登録解除の可能性があります。あなたは、オブザーバブル/ストアではなく、実際にサブスクリプションを購読解除する必要があります。例えば、 。あなたはこのようなサブスクリプションがある場合:あなたはいくつかのコードを取り残さかどうかわからない、また

ngOnDestroy() { 
    // unsubscribe the observable 
    this.subscription.unsubscribe(); 
    } 

が、あなたがあなたの店を嘲笑方法は、それはおそらくだろう:

this.subscription = this._store 
    .select('users') 
    .subscribe(users => { 
     this.users = users; 
    }); 

を、あなたは、このよう退会します実際の店舗を使うだけで十分ですし、ディスパッチなどでスパイしてください。

+1

あなたの答えをありがとう:)私のコンポーネントとテストが本当に重要なので、いくつかのコードは除外されました。私はあなたのコメントに記述しているように既に退会していますので、私のエラーは他のところにあるのでしょうか...。 'this.userStore = this.store.let(fromRoot.get).subscribe((state:any)=> {/ /接続の場合はページを歓迎する}}; ' – Megan

関連する問題