Redux-Observable 只读测试 epics
Redux-Observable testing readonly epics
我想测试以下史诗:
authEpics.logoutEpic = function (action$, _, deps) {
return action$.pipe(
ofType(authActions.logout),
tap(() => {
const { history, browser } = deps;
browser.localStorage.removeItem('user');
history.push(ROUTES.LOGIN);
}),
ignoreElements()
);
};
这是测试用例:
describe('Logout Epic', () => {
test('should remove user from localStorage', (done) => {
scheduler.run((helpers) => {
const { hot, expectObservable } = helpers;
const action$ = hot('a', {
a: authActions.logout(),
});
const deps = testUtils.mockEpicDependencies();
const output$ = authEpics.logoutEpic(action$, null, deps);
// Statement 1.
expectObservable(output$).toBe('');
// Statement 2.
output$.subscribe({
complete: () => {
expect(deps.browser.localStorage.removeItem).toHaveBeenCalledWith('user');
expect(deps.history.push).toHaveBeenCalledWith(ROUTES.LOGIN);
done();
}
});
});
});
根据 ignoreElements 的定义,我无法理解以下观察结果:
- 在声明 1 中,我认为
expectObservable(output$).toBe('|')
应该有效,但它没有。相反 expectObservable(output$).toBe('')
有效。
- 在语句 2 中,
complete
函数从未被调用。
为了让测试用例工作,我不得不刷新承诺队列(而不是使用 expectObservable
)。这是修改后的测试用例:
describe('Logout Epic', () => {
test('should remove user from localStorage', (done) => {
scheduler.run(async (helpers) => {
const { hot } = helpers;
const action$ = hot('a', {
a: authActions.logout(),
});
const deps = testUtils.mockEpicDependencies();
const output$ = authEpics.logoutEpic(action$, null, deps);
// *** Flush the promise queue ***
await new Promise((resolve) => resolve());
expect(deps.browser.localStorage.removeItem).toHaveBeenCalledWith('user');
expect(deps.history.push).toHaveBeenCalledWith(ROUTES.LOGIN);
done();
});
});
这太痛苦了,对我不起作用。
const pingAuthEpic = (action$: any) => action$.pipe(
ofType(SET_ONLINE),
mergeMap(() => interval(PING_AUTH_INTERVAL).pipe(
mergeMap(() => of({ type: 'PING_AUTH' })),
takeUntil(action$.ofType(SET_OFFLINE)),
)),
);
欢迎了解它为何挂起和玩笑超时的任何想法...
另一种选择是在依赖项中传递一个标志,告诉史诗是否应该emmit/ignoreElements,并将其默认为真。然后测试可以将此标记为 false 并正常使用输出。
如果您想使用大理石测试来验证时间(假设您需要对本地存储的调用是异步的)。您可以使用 rxjs testScheduler (https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/testing/marble-testing.md) 并让依赖项调用一个主题,然后您可以将其传递给 expectObservable。这允许您检查依赖项是否在正确的时间使用正确的参数调用。
我想测试以下史诗:
authEpics.logoutEpic = function (action$, _, deps) {
return action$.pipe(
ofType(authActions.logout),
tap(() => {
const { history, browser } = deps;
browser.localStorage.removeItem('user');
history.push(ROUTES.LOGIN);
}),
ignoreElements()
);
};
这是测试用例:
describe('Logout Epic', () => {
test('should remove user from localStorage', (done) => {
scheduler.run((helpers) => {
const { hot, expectObservable } = helpers;
const action$ = hot('a', {
a: authActions.logout(),
});
const deps = testUtils.mockEpicDependencies();
const output$ = authEpics.logoutEpic(action$, null, deps);
// Statement 1.
expectObservable(output$).toBe('');
// Statement 2.
output$.subscribe({
complete: () => {
expect(deps.browser.localStorage.removeItem).toHaveBeenCalledWith('user');
expect(deps.history.push).toHaveBeenCalledWith(ROUTES.LOGIN);
done();
}
});
});
});
根据 ignoreElements 的定义,我无法理解以下观察结果:
- 在声明 1 中,我认为
expectObservable(output$).toBe('|')
应该有效,但它没有。相反expectObservable(output$).toBe('')
有效。 - 在语句 2 中,
complete
函数从未被调用。
为了让测试用例工作,我不得不刷新承诺队列(而不是使用 expectObservable
)。这是修改后的测试用例:
describe('Logout Epic', () => {
test('should remove user from localStorage', (done) => {
scheduler.run(async (helpers) => {
const { hot } = helpers;
const action$ = hot('a', {
a: authActions.logout(),
});
const deps = testUtils.mockEpicDependencies();
const output$ = authEpics.logoutEpic(action$, null, deps);
// *** Flush the promise queue ***
await new Promise((resolve) => resolve());
expect(deps.browser.localStorage.removeItem).toHaveBeenCalledWith('user');
expect(deps.history.push).toHaveBeenCalledWith(ROUTES.LOGIN);
done();
});
});
这太痛苦了,对我不起作用。
const pingAuthEpic = (action$: any) => action$.pipe(
ofType(SET_ONLINE),
mergeMap(() => interval(PING_AUTH_INTERVAL).pipe(
mergeMap(() => of({ type: 'PING_AUTH' })),
takeUntil(action$.ofType(SET_OFFLINE)),
)),
);
欢迎了解它为何挂起和玩笑超时的任何想法...
另一种选择是在依赖项中传递一个标志,告诉史诗是否应该emmit/ignoreElements,并将其默认为真。然后测试可以将此标记为 false 并正常使用输出。
如果您想使用大理石测试来验证时间(假设您需要对本地存储的调用是异步的)。您可以使用 rxjs testScheduler (https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/testing/marble-testing.md) 并让依赖项调用一个主题,然后您可以将其传递给 expectObservable。这允许您检查依赖项是否在正确的时间使用正确的参数调用。