我有一个传奇,它会侦听模型更新并向网络发起一次保存,并以1秒的速度去除:
export default function* graphModelUpdate() {
const modelChangeDebounceTime = 1000;
let task;
while (true) {
const action = yield take(IllustrationsActions.GRAPH_MODEL_CHANGED);
if (task) {
yield cancel(task);
}
task = yield fork(function* (payload) {
yield call(delay, modelChangeDebounceTime);
yield put(IllustrationsActions.apiUpdateGraph(payload));
}, action.payload);
}
}
然后我按照redux-saga docs和jest docs regarding timers编写了这个测试,测试saga的效果而不是它的实现:
jest.useFakeTimers();
describe('graphModelUpdate saga', () => {
let dispatched;
let mockState;
let subscribers = [];
const emitAction = (action) => {
subscribers.forEach(cb => cb(action));
};
const options = {
subscribe: callback => {
subscribers.push(callback);
return () => subscribers = subscribers.filter(cb => cb !== callback);
},
dispatch: (action) => dispatched.push(action),
getState: () => mockState
};
beforeEach(() => {
dispatched = [];
mockState = {};
});
it('should listen for IllustrationsActions.GRAPH_MODEL_CHANGED and dispatch IllustrationsActions.apiUpdateGraph, debounced by 1 second', () => {
runSaga(options, graphModelUpdate);
emitAction(IllustrationsActions.graphModelChanged('model one'));
emitAction(IllustrationsActions.graphModelChanged('model two'));
emitAction(IllustrationsActions.graphModelChanged('model three'));
expect(dispatched).toEqual([]);
jest.runTimersToTime(1500);
expect(dispatched).toEqual([
IllustrationsActions.apiUpdateGraph('model three')
]);
});
});
问题在于,由于saga使用异步运行的fork
,所以在调度去抖动作之前执行最终expect
,无论假冒时间过多({{1} }),使测试总是失败。
我该如何处理这种情况?
答案 0 :(得分:0)
伪造的计时器可以正确地提前时间,但是仍然有必要释放事件循环,以便生成器可以恢复执行,并且只有在我们可以继续执行期望的情况下
不使用setTimeout
的情况下执行此操作的示例(因为它已经被玩笑嘲笑了):
jest.runTimersToTime(1500);
await Promise.resolve(); // generator resumes execution
expect(dispatched).toEqual([
IllustrationsActions.apiUpdateGraph('model three')
]);