2017-04-03 16 views
0

私は、叙事詩をテストするためにdocumentationの手順に従っています。Redux-observable:叙事詩の冗談テストに失敗しました

... 
store.dispatch({ type: FETCH_USER }); 

expect(store.getActions()).toEqual([ 
    { type: FETCH_USER }, 
    { type: FETCH_USER_FULFILLED, payload } 
]); 
... 

しかし、後で次のように2番目の処理が行われたために失敗しました。

Test failed 
    Expected value to equal: 
     [{"type": "FETCH_USER"}, {"type": "FETCH_USER_FULFILLED", "payload": [some]}] 
    Received: 
     [{"type": "FETCH_USER"}] 

    Difference: 

    - Expected 
    + Received 

    @@ -1,20 +1,5 @@ 
    Array [ 
     Object {"type": "FETCH_USER"}, 
     Object {"type": "FETCH_USER_FULFILLED", "payload": [some]} ] // this is what should be. 

私は、発送がいつ終了したか、またはそのようなことを知っておくべきだと思います。 どうすればこの問題を解決できますか?

私はここで

は私の叙事詩である)フェッチ()、代わりにajax.getJSONのRx.Observable.fromPromise(使用。

const fetchUserEpic = (action$) => 
    action$ 
    .ofType(FETCH_USER) 
    .mergeMap(() => { 
     return Rx.Observable.fromPromise(api.fetchUser()) 
     .map((users) => ({ 
      type: FETCH_USER_FULFILLED, 
      payload: { users } 
     })) 
     .catch((error) => Rx.Observable.of({ 
      type: FETCH_USER_ERROR, 
      payload: { error } 
     })) 
     .takeUntil(action$.ofType(FETCH_USER_CANCELLED)) 
    }) 

答えて

4

理由は、約束は必ずnext microtaskに解決するということですので、あなたのapi.fetchUser()は同期放出されていません。

あなたは次のマイクロタスクまで待たPromise.resolve().then(() => expect(store.getActions).toEqual(...)のようなものを使用し、それをモックするか必要があります、またはあなたはReduxのを使用せずに直接あなたの叙事詩のテストを試してみることができます。

it('Epics with the appropriate input and output of actions', (done) => { 
    const action$ = ActionsObservable.of({ type: 'SOMETHING' }); 

    somethingEpic(action$, store) 
    .toArray() // collects everything in an array until our epic completes 
    .subscribe(actions => { 
     expect(actions).to.deep.equal([ 
     { type: 'SOMETHING_FULFILLED' }// whatever actions 
     ]); 

     done(); 
    }); 
}); 

これは、私(または他の誰か)がそれらを書き込む時間があるとき、これが私たちの好ましいテストストーリーになります。だから、あなたのテストでreduxとミドルウェアを使うのではなく、私たち自身のモックで叙事詩関数を直接呼び出すだけです。はるかに簡単で清潔です。そのアプローチで

は、我々は新たな依存性注入の機能を活用することができますReduxの-観測可能:https://redux-observable.js.org/docs/recipes/InjectingDependenciesIntoEpics.html


import { createEpicMiddleware, combineEpics } from 'redux-observable'; 
import { ajax } from 'rxjs/observable/dom/ajax'; 
import rootEpic from './somewhere'; 

const epicMiddleware = createEpicMiddleware(rootEpic, { 
    dependencies: { getJSON: ajax.getJSON } 
}); 

// Notice the third argument is our injected dependencies! 
const fetchUserEpic = (action$, store, { getJSON }) => 
    action$.ofType('FETCH_USER') 
    .mergeMap(() => 
     getJSON(`/api/users/${payload}`) 
     .map(response => ({ 
      type: 'FETCH_USER_FULFILLED', 
      payload: response 
     })) 
    ); 

import { ActionsObservable } from 'redux-observable'; 
import { fetchUserEpic } from './somewhere/fetchUserEpic'; 

const mockResponse = { name: 'Bilbo Baggins' }; 
const action$ = ActionsObservable.of({ type: 'FETCH_USERS_REQUESTED' }); 
const store = null; // not needed for this epic 
const dependencies = { 
    getJSON: url => Observable.of(mockResponse) 
}; 

// Adapt this example to your test framework and specific use cases 
fetchUserEpic(action$, store, dependencies) 
    .toArray() // buffers all emitted actions until your Epic naturally completes() 
    .subscribe(actions => { 
    assertDeepEqual(actions, [{ 
     type: 'FETCH_USER_FULFILLED', 
     payload: mockResponse 
    }]); 
    }); 
+1

私は解決策が正しいことを参照してください。私は「TypeError:プロパティの '_location' of null」を読み取ることができませんが、問題の外です。 – Oscar

+0

私は数時間この頭を叩いていました...これを試して、 "toArrayは関数ではありません"というエラーを出しました。 –

+0

ok、インポート 'rxjs/add/operator/toArray'を追加して解決しました... –

関連する問題