测试调用其他史诗的 Observable 史诗
Testing Observable epic which invokes other epic
我正在尝试测试一个 Redux Observable 史诗,它调度一个动作来调用另一个史诗。不知何故调用的史诗没有被调用。
假设我的 epics 看起来像这样;
const getJwtEpic = (action$, store, { api }) =>
action$.ofType('GET_JWT_REQUEST')
.switchMap(() => api.getJWT()
.map(response => {
if (response.errorCode > 0) {
return {
type: 'GET_JWT_FAILURE',
error: { code: response.errorCode, message: response.errorMessage },
};
}
return {
type: 'GET_JWT_SUCCESS',
idToken: response.id_token,
};
})
);
const bootstrapEpic = (action$, store, { api }) =>
action$.ofType('BOOTSTRAP')
.switchMap(() =>
action$.filter(({ type }) => ['GET_JWT_SUCCESS', 'GET_JWT_FAILURE'].indexOf(type) !== -1)
.take(1)
.mergeMap(action => {
if (action.type === 'GET_JWT_FAILURE') {
return Observable.of({ type: 'BOOTSTRAP_FAILURE' });
}
return api.getProfileInfo()
.map(({ profile }) => ({
type: 'BOOTSTRAP_SUCCESS', profile,
}));
})
.startWith({ type: 'GET_JWT_REQUEST' })
);
当我尝试使用以下代码在 Jest 中测试 bootstrapEpic
时;
const response = {};
const api = { getJWT: jest.fn() };
api.getJWT.mockReturnValue(Promise.resolve(response));
const action$ = ActionsObservable.of(actions.bootstrap());
const epic$ = epics.bootstrapEpic(action$, null, { api });
const result = await epic$.toArray().toPromise();
console.log(result);
console.log
调用给我以下输出;
[ { type: 'GET_JWT_REQUEST' } ]
不知何故 getJwtEpic
根本没有被调用。我想这与 action$
observable 不调度 GET_JWT_REQUEST
操作有关,但我不明白为什么。欢迎所有帮助!
假设 actions.rehydrate()
returns 类型为 BOOTSTRAP
的操作并且 gigya
内容是错字,
getJwtEpic
没有被调用,因为你没有自己调用它 当你通过手动调用它们来测试 epics 时,那么它只是一个 returns 一个 Observable 的函数,没有中间件或其他任何知识。作为根史诗的一部分连接 getJwtEpic
并为它提供 (action$, store)
的管道是中间件的一部分,您不会在测试中使用它。
这是正确的方法,在没有 redux/middleware 的情况下单独测试它们。因此,您通过向它提供操作和依赖项,然后断言它发出的操作和它调用的依赖项来单独测试每个史诗。
您将像这样测试成功路径:
const api = {
getProfileInfo: () => Observable.of({ profile: 'mock profile' })
};
const action$ = ActionsObservable.of(
actions.rehydrate(),
{ type: 'GET_JWT_SUCCESS', idToken: 'mock token' }
);
const epic$ = epics.bootstrapEpic(action$, null, { api });
const result = await epic$.toArray().toPromise();
expect(result).toEqual([
{ type: 'GET_JWT_REQUEST' },
{ type: 'BOOTSTRAP_SUCCESS', profile: 'mock profile' }
]);
然后你将在另一个测试中测试失败路径,方法是做同样的事情,除了给它 GET_JWT_FAILURE
而不是 GET_JWT_SUCCESS
。然后您也可以单独测试 getJwtEpic
。
顺便说一句,ofType
接受任意数量的类型,所以你可以只做 action$.ofType('GET_JWT_SUCCESS', 'GET_JWT_FAILURE')
我正在尝试测试一个 Redux Observable 史诗,它调度一个动作来调用另一个史诗。不知何故调用的史诗没有被调用。
假设我的 epics 看起来像这样;
const getJwtEpic = (action$, store, { api }) =>
action$.ofType('GET_JWT_REQUEST')
.switchMap(() => api.getJWT()
.map(response => {
if (response.errorCode > 0) {
return {
type: 'GET_JWT_FAILURE',
error: { code: response.errorCode, message: response.errorMessage },
};
}
return {
type: 'GET_JWT_SUCCESS',
idToken: response.id_token,
};
})
);
const bootstrapEpic = (action$, store, { api }) =>
action$.ofType('BOOTSTRAP')
.switchMap(() =>
action$.filter(({ type }) => ['GET_JWT_SUCCESS', 'GET_JWT_FAILURE'].indexOf(type) !== -1)
.take(1)
.mergeMap(action => {
if (action.type === 'GET_JWT_FAILURE') {
return Observable.of({ type: 'BOOTSTRAP_FAILURE' });
}
return api.getProfileInfo()
.map(({ profile }) => ({
type: 'BOOTSTRAP_SUCCESS', profile,
}));
})
.startWith({ type: 'GET_JWT_REQUEST' })
);
当我尝试使用以下代码在 Jest 中测试 bootstrapEpic
时;
const response = {};
const api = { getJWT: jest.fn() };
api.getJWT.mockReturnValue(Promise.resolve(response));
const action$ = ActionsObservable.of(actions.bootstrap());
const epic$ = epics.bootstrapEpic(action$, null, { api });
const result = await epic$.toArray().toPromise();
console.log(result);
console.log
调用给我以下输出;
[ { type: 'GET_JWT_REQUEST' } ]
不知何故 getJwtEpic
根本没有被调用。我想这与 action$
observable 不调度 GET_JWT_REQUEST
操作有关,但我不明白为什么。欢迎所有帮助!
假设 actions.rehydrate()
returns 类型为 BOOTSTRAP
的操作并且 gigya
内容是错字,
getJwtEpic
没有被调用,因为你没有自己调用它 当你通过手动调用它们来测试 epics 时,那么它只是一个 returns 一个 Observable 的函数,没有中间件或其他任何知识。作为根史诗的一部分连接 getJwtEpic
并为它提供 (action$, store)
的管道是中间件的一部分,您不会在测试中使用它。
这是正确的方法,在没有 redux/middleware 的情况下单独测试它们。因此,您通过向它提供操作和依赖项,然后断言它发出的操作和它调用的依赖项来单独测试每个史诗。
您将像这样测试成功路径:
const api = {
getProfileInfo: () => Observable.of({ profile: 'mock profile' })
};
const action$ = ActionsObservable.of(
actions.rehydrate(),
{ type: 'GET_JWT_SUCCESS', idToken: 'mock token' }
);
const epic$ = epics.bootstrapEpic(action$, null, { api });
const result = await epic$.toArray().toPromise();
expect(result).toEqual([
{ type: 'GET_JWT_REQUEST' },
{ type: 'BOOTSTRAP_SUCCESS', profile: 'mock profile' }
]);
然后你将在另一个测试中测试失败路径,方法是做同样的事情,除了给它 GET_JWT_FAILURE
而不是 GET_JWT_SUCCESS
。然后您也可以单独测试 getJwtEpic
。
顺便说一句,ofType
接受任意数量的类型,所以你可以只做 action$.ofType('GET_JWT_SUCCESS', 'GET_JWT_FAILURE')