2017-08-07 38 views
2

我正在努力如何測試retryWhen運營商在redux-observable epic。基於this example取自docs,我叉了this jsbin我試圖測試的情況下,響應失敗2次,之後,它返回一個有效的響應。RxJS Redux-Observables測試重試當在一個史詩

以下是部分代碼。對於整個實施,請使用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] 
     }); 
    }); 
    ... 

}); 

如果您在jsbin中總是empty陣列的實際行動響應。

+0

您好!你有沒有嘗試過測試你的重試?當沒有其他所有東西和所有抽象?因爲我或他們需要花費大量的時間來了解所有的事情,所以有人可能很難幫助你。 – jayphelps

+0

@jayphelps感謝您的快速回復。問題似乎是,當使用'retry'或'retryWhen'重試從一開始執行整個操作時,不僅僅是重試內部ajax observable(在switchMap中)。我根據上面的例子做了很多測試,你可以看到[這裏](http://jsbin.com/hekener/36/edit?js,output),如果你試圖改變重試次數(' .retry(3)')或更改大理石響應('response:[' - #a |''),您可以看到實際的幀是幀數和重試次數的乘積。 – stelioschar

回答

1

我有一個類似的問題,我試圖測試一個Angular HttpInterceptor,嘗試三次嘗試之間的延遲。正如您在評論中提到的那樣,重試時每次錯誤後重新訂閱觀察值。這意味着如果你有一個可觀察的錯誤(例如cold('#|')),你將會在重試時總是得到一個錯誤,因爲在每次重試時會重新訂閱相同的可觀察錯誤。

它看起來像一個黑客,但我創建了這個簡單的類,按照給定的順序訂閱不同的observables。

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|')); 

我希望別人也就不那麼哈克解決方案,但這種情況正在爲我工​​作。