使用 React、Jest、Redux 和 Thunk 进行无限循环测试

Chr*_*rea 7 firebase reactjs jestjs redux-thunk react-redux

我有一个带有 Jest 测试套件的 React 应用程序。应用程序使用 redux,测试套件使用 redux-mock-store。我正在使用 react-thunk 中间件来延迟调度操作,因为应用程序需要与远程 Firebase 数据库同步数据。我希望我的测试套件在向 Redux 分派操作后验证某些条件,如下所示:

import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';

// This is my custom async action generator.
import { asyncAction } from './some/path';

const createMockStore = configureMockStore([thunk]);

test("Test", (done) => {
    const store = createMockStore({});
    const data = { ... };
    store.dispatch(asyncAction(data)).then(() => {
        expect(someCondition);
        done();
    });
});
Run Code Online (Sandbox Code Playgroud)

该测试使用 Jest 返回的 done 处理程序来等待 store.dispatch 返回的 promise 完成。但是,promise 永远不会执行,测试进入无限循环,Jest 失败并出现以下异常:

Assertion failed: new_time >= loop->time, file c:\ws\deps\uv\src\win\core.c, line 309
error Command failed with exit code 3221226505.
Run Code Online (Sandbox Code Playgroud)

起初我以为我的自定义异步操作生成器返回的承诺有问题,但请注意它是如何从 Firebase 返回承诺的(查看内部 return 语句,外部 return 语句是 redux-thunk 调度的函数) :

import database from '../firebase/firebase';

export const asyncAction = (data = {}) => {
    return (dispatch) => {
        return database.ref('someCollection').push(data).then((ref) => {
            dispatch({ type: 'SOME_TYPE', id: ref.key, ...data });
        });
    };
}; 
Run Code Online (Sandbox Code Playgroud)

然后我想也许我设置 Firebase 的方式有问题,但我已经验证应用程序和测试套件都成功保存了数据。这是 Firebase 配置:

import * as firebase from 'firebase/app';
import 'firebase/database';

firebase.initializeApp({ ... });

const database = firebase.database();
export { database as default };
Run Code Online (Sandbox Code Playgroud)

然后我想可能是 Redux 或 redux-thunk 中间件有问题,但我已经验证应用程序正在成功保存数据。这是我的 Redux 配置:

import { applyMiddleware, createStore, combineReducers, compose } from 'redux';
import thunk from 'redux-thunk';

const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;

export default () => {
    const reducer = combineReducers({ ... });
    const enhancer = composeEnhancers(applyMiddleware(thunk));
    return createStore(reducer, enhancer);
};
Run Code Online (Sandbox Code Playgroud)

对我来说这一切都很好。我无法确定是什么导致 Jest 进入无限循环。在此先感谢您的帮助。

Car*_*iel 2

所以我在 Github 上偶然发现了这个冗长的问题(Google 上的关键字“断言失败:new_time >=loop->time ”),大约是三年前的事了。它是(libuv)Node 用于异步 I/O 的库,也是问题所在的地方。经过简短的阅读后,这个问题似乎只存在于英特尔的 Ice Lake CPU 上(目前)。虽然该问题已在库中修复,但它需要至少 14.6.0 的 Node 版本,其中包括修复的库实现。建议更新到此版本(可能是最简单的选择,但不是唯一的选择)。