javascript - 使用 jest fake 计时器测试 redux-saga debounce

标签 javascript reactjs jestjs redux-saga

我有一个传奇,它监听模型更新并触发保存到网络,并以 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 ,测试传奇的效果而不是其实现:

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')
        ]);
    });
});

问题是,由于传奇使用 fork异步运行,最终的expect在调度 debounced 操作之前执行,无论经过多少虚假时间 ( jest.runTimersToTime(1500) ),都会导致测试失败。

我该如何处理这种情况?

最佳答案

假定时器正确地提前了时间,但仍然需要释放事件循环,以便生成器恢复执行,并且只有在我们可以继续执行预期之后

有关如何在不使用 setTimeout 的情况下执行此操作的示例(因为它已被 Jest mock ):

jest.runTimersToTime(1500);
await Promise.resolve(); // generator resumes execution
expect(dispatched).toEqual([
   IllustrationsActions.apiUpdateGraph('model three')
]);

关于javascript - 使用 jest fake 计时器测试 redux-saga debounce,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49232702/

相关文章:

javascript - 如何将插件添加到 Bootstrap

javascript - 如何知道异步函数调用何时完成(Javascript)

javascript - 如何在map函数中调用api

javascript - 如何在react-native中控制打开/关闭模式

php - 在外部 JS 文件中传递 PHP 变量

javascript - jQuery toLowerCase 然后应用 Capitalize CSS Style

javascript - 如何检测某人在输入字段中输入的单位

node-inspector - 使用 node-inspector 调试 Jest 测试用例

javascript - Jest 基础 : Testing function from component

javascript - Jest : Specific selector