【问题标题】:RxJS Redux-Observables Test retryWhen inside an epicRxJS Redux-Observables 测试 retryWhen 在史诗中
【发布时间】:2018-01-14 18:00:33
【问题描述】:

我正在努力研究如何在 redux-observable epic 中测试 retryWhen 运算符。基于取自docsthis example,我分叉了this jsbin,在那里我尝试测试响应失败2 次然后返回有效响应的情况。

以下是部分代码。整个实现请使用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 数组中。

【问题讨论】:

  • 您好!您是否尝试过在没有其他所有内容和所有抽象的情况下测试您的 retryWhen?像我这样的人可能很难帮助您,否则他们需要花费大量时间来了解所有内容。
  • @jayphelps 感谢您的快速回复。问题似乎是当使用retryretryWhen 时重试从头开始执行整个操作,而不仅仅是重试内部 ajax observable(内部 switchMap)。我根据上面的例子做了很多测试,你可以看到here如果你尝试改变重试次数(.retry(3))或改变响应弹珠(response: ['--#a|')你可以看到实际frame 是帧数和重试次数的乘积。

标签: unit-testing rxjs rxjs5 redux-observable


【解决方案1】:

我有一个类似的问题,我试图测试一个 Angular HttpInterceptor,它最多尝试 3 次,尝试之间有延迟。正如您在 cmets 中提到的, retryWhen 会在每次错误后重新订阅 observable。这意味着如果您有一个可观察到的错误(例如cold('#|')),您将始终在 retryWhen 中收到一个错误,因为它在每次重试时重新订阅了相同的可观察到的错误。

这似乎是一个 hack,但我创建了这个简单的类,它按给定的顺序订阅不同的 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|'));

我希望其他人会有一个不那么老套的解决方案,但现在这对我有用。

【讨论】:

    猜你喜欢
    • 2021-11-13
    • 2019-01-23
    • 1970-01-01
    • 2020-12-30
    • 2018-09-15
    • 1970-01-01
    • 1970-01-01
    • 2021-01-11
    • 1970-01-01
    相关资源
    最近更新 更多