我正在使用React和Redux Observables创建一个Web应用程序,我想为我的史诗之一的超时情况创建一个单元测试。
这是史诗:
export const loginUserEpic = (action$: ActionsObservable<any>, store, { ajax, scheduler }): Observable<Action> =>
action$.pipe(
ofType<LoginAction>(LoginActionTypes.LOGIN_ACTION),
switchMap((action: LoginAction) =>
ajax({
url,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: { email: action.payload.username, password: action.payload.password },
}).pipe(
timeout(timeoutValue, scheduler),
map((response: AjaxResponse) => loginSuccess(response.response.token)),
catchError((error: Error) => of(loginFailed(error))),
),
),
);
这是我的测试:
it('should handle a timeout error', () => {
// My current timeout value is 20 millseconds
const inputMarble = '------a';
const inputValues = {
a: login('fake-user', 'fake-password'),
};
const outputMarble = '--b';
const outputValues = {
b: loginFailed(new Error('timeout')),
};
const ajaxMock = jest.fn().mockReturnValue(of({ response: { token: 'fake-token' } }));
const action$ = new ActionsObservable<Action>(ts.createHotObservable(inputMarble, inputValues));
const outputAction = loginUserEpic(action$, undefined, { ajax: ajaxMock, scheduler: ts });
// I am not sure what error to expect here...
ts.expectObservable(outputAction).toBe(outputMarble, outputValues);
ts.flush();
expect(ajaxMock).toHaveBeenCalled();
});
我期望的是Epic会引发超时错误,因为我的超时值为20毫秒,观察者在发出值之前延迟了60毫秒。然后,我将接受此错误并最终进行比较以通过测试。
很遗憾,没有引发超时错误。我在做错什么吗?
答案 0 :(得分:0)
您在调用timeout
后在链中使用ajax()
,该of({ ... })
仅返回ajaxMock
(timeout
),因此of
永远不会被触发,因为{{ 1}}立即发出。
如果要测试timeout
运算符,则需要将delay
添加到ajaxMock
中:
const ajaxMock = () => of({ response: { token: 'fake-token' } }).pipe(delay(30, ts));
这是您的演示:https://stackblitz.com/edit/rxjs6-demo-pha4qp?file=index.ts
如果登录请求始于60
,并且您添加了30
延迟,那么在80
处,您将收到TimeoutError。
[0: Object
frame: 80
notification: Notification
error: undefined
hasValue: true
kind: "N"
value: Object
error: Error
message: "Timeout has occurred"
name: "TimeoutError"
]