2017-08-07 8 views
2

redux-observable epicretryWhenオペレータをテストする方法に苦労しています。 this exampledocsから取ったところで、私はthis jsbinをフォークしました。ここで、応答が2回失敗した後、有効な応答を返すケースをテストしようとしています。RxJS Redux-Observables叙事詩の中でテストretryWhen

以下はコードの一部です。あなたはいつもempty、アレイ内の実際の行動をjsbinで応答を確認した場合、全体の実装についてthis jsbin

let RetryStrategy = attempts => attempts 
    .zip(Observable.range(1, 4)) 
    .flatMap(([error, i]) => { 
     if (i > 3) { 
      return Observable.throw('Network error occured') 
     } 
     return Observable.timer(i * 1000) 
    }) 


const fetchFooEpic = (action$, store, call = indirect.call) => 
    action$.ofType('FETCH_FOO') 
     .mergeMap(action => 
      call(api.fetchFoo, action.payload.id) 
       .map(payload => ({ type: 'FETCH_FOO_FULFILLED', payload })) 
       .retryWhen(RetryStrategy) 
       .takeUntil(action$.ofType('FETCH_FOO_CANCELLED')) 
       .catch(error => of({ 
        type: 'FETCH_FOO_REJECTED', 
        payload: error.xhr.response, 
        error: true 
       })) 
     ); 

describe('fetchFooEpic',() => { 
    ... 
    it.only('handles errors correctly',() => { 
     const badResponse = { message: 'BAD STUFF' }; 
     const response = { id: 123, name: 'Bilbo' }; 

     expectEpic(fetchFooEpic, { 
      expected: ['-----a|', { 
       a: { type: 'FETCH_FOO_FULFILLED', payload: response } 
      }], 
      action: ['(a|)', { 
       a: { type: 'FETCH_FOO', payload: { id: 123 } } 
      }], 
      response: ['-#-#-a|', { 
       a: response 
      }, { xhr: { badResponse } }], 
      callArgs: [api.fetchFoo, 123] 
     }); 
    }); 
    ... 

}); 

を使用してください。

+0

こんにちは!あなたはあなたの再試行を試してみましたか?誰かが私を助けてくれるのは難しいかもしれません。あるいは、すべてを理解するために些細な時間を費やす必要があるかもしれません。 – jayphelps

+0

@jayphelpsご返信ありがとうございます。この問題は、 'retry'や' retryWhen'を使って、最初からアクション全体をやり直して、内側のajax observable(switchMapの内側)を再試行するのではなく、再試行しているようです。上記の例に基づいてテストを行いました。リトライ回数( ' .retry(3) ')、または応答の大理石(' response:[' - #a |' ')を変更すると、実際のフレームはフレームと再試行回数の乗算であることがわかります。 – stelioschar

答えて

1

私は、試行間の遅延で最大3回試行するAngular HttpInterceptorをテストしようとしていたのと同様の問題がありました。コメントで述べたように、retryWhenは各エラーの後にobservableに再登録します。つまり、エラーが発生した場合(例:cold('#|'))、再試行ごとに同じエラーが再表示されるため、常にretryWhenにエラーが発生します。

これはハックのようですが、私は与えられた順序で異なる観察可能事項に購読するこの単純なクラスを作成しました。

次のように私はそれを使用する私のテストで
class MultiObservable extends Observable<any> { 
    constructor(observables: Observable<any>[]) { 
     let subscriptionIdx = 0; 
     super((subscriber: Subscriber<any>) => 
       observables[subscriptionIdx++].subscribe(subscriber)); 
    } 
    } 

const testObservable = new MultiObservable([ 
    cold('#|', null, { status: 400 }), 
    cold('a|') 
    ]); 

    next.handle.and.returnValue(testObservable); 
    const actual = interceptor.intercept(req, next); 
    expect(actual).toBeObservable(cold('---a|')); 

私は他の誰かが少ないハックソリューションを持っていることを望んだが、これが今の私のために働いています。

関連する問題