我在如何测试retryWhen
中的redux-observable epic
运算符方面苦苦挣扎。基于this example取自docs,我分叉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
数组。
答案 0 :(得分:2)
我有一个类似的问题,我试图测试一个Angular HttpInterceptor,尝试最多三次尝试之间的延迟。正如您在评论中提到的那样,重试在每次错误后重新订阅observable。这意味着如果您有一个可观察的错误(例如cold('#|')
),您将始终在重试时收到错误,因为重新订阅了每次重试时可观察到的相同错误。
这似乎是一个黑客,但我创建了这个简单的类,按照给定的顺序订阅不同的observable。
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|'));
我希望其他人会有一个不太讨厌的解决方案,但现在这对我有用。