Redux 警告只出现在测试中

Redux warning only appearing in tests

我用 React redux 创建了一个井字游戏。

我正在使用 create-react-app

我有以下商店:

import {createStore, combineReducers} from 'redux';
import gameSettingsReducer from './reducers/gameSettings.js';
import gameStatusReducer from './reducers/gameStatus.js';


const rootReducer = combineReducers({gameSettings: gameSettingsReducer,
                   gameStatus: gameStatusReducer});

export const defaultGameStatus = {
      currentPlayerSymbol: "X",
      turnNumber: 0,
      currentView: "start-menu", //one of "start-menu", "in-game", "game-over"
      winner: "draw", //one of "X", "O", "draw"
      board: [["E", "E", "E"],
              ["E", "E", "E"],
              ["E", "E", "E"]],
      lastMove: []
};

const store = createStore(rootReducer, {
    gameSettings:{
        playerSymbol: "X",  //one of "X", "O"
        difficulty: "easy"  //one of "easy", "hard"
    },
    gameStatus: defaultGameStatus
});


export default store;

一切如我所料。除了我正在 运行 测试 (npm test) 之外,以下内容出现在控制台中:

console.error node_modules\redux\lib\utils\warning.js:14
  No reducer provided for key "gameStatus"
console.error node_modules\redux\lib\utils\warning.js:14
  Unexpected key "gameStatus" found in preloadedState argument passed to createStore. Expected to find one of the known reducer keys instead: "gameSettings". Unexpected keys will be ignored.

在我进行的几次测试中,我什至没有测试商店。所以我想这是在编译代码时出现的。 我尝试将 console.log(gameStatusReducer) 放在 root reducer 行之前。 它表明 gameStatusReducer 未定义。

由于 gameSettingsReducer 和 gameStatusReducer 的创建方式非常相似,我不知道这个错误是从哪里来的,甚至不知道如何进一步调查这个问题。这仅在 运行 测试时出现。 运行 该应用程序未显示此问题,并且该应用程序按预期运行。

所以,问题是:

在用我的头敲打键盘很多次之后,我找到了一些线索。

快速修复:gameStateReducer 制作一个正常的 export 而不是 default 并使用 import { gameStateReducer } from // ... 将其导入其他地方.

Jest 会自动模拟某些导入,显然在这种情况下它存在错误,或者它需要某种 react-create-app 尚未提供的配置。

至于为什么 Jest 甚至会记录该错误(考虑到相关代码未在任何测试中导入),我想这是由于其内部工作原理所致。

支持这一点的是以下证据:向 npm test 脚本添加 --testPathPattern 标志仅匹配以 .test.js 结尾的文件不会改变行为并且错误仍然出现。

如何调查问题: 我首先弄清楚导致错误日志的代码是否在测试中(间接地它可能是,用 import 例如)。排除这种可能性后,我开始模拟传递给 combineReducers 的函数,以确保任何更改都会影响错误日志的结果,而它们确实如此。只需添加:

gameStatus: gameStatusReducer || (() => ())

...已经解决了问题,这意味着问题出在 import 以及 Jest/babel-jest 的处理方式上。

如果我要进一步调查这个问题,我会用 Jest 创建我自己的安装并提供我自己的配置,看看 Jest 是否仍然编译整个应用程序。如果您使用 react-create-app.

,将配置选项传递给 Jest 似乎很重要

祝你好运!

要合并 reducer,确定 import { combineReducers } from 'redux'; 而不是将它们合并成一个对象并将其提供给 createStore。

例如:

    const appReducer = combineReducers({
      gameSettings: ...,
      gameStatus: ...,
    });

  const store = createStore(
    appReducer,
    enhancer,
  );

也有这个错误,但使用的是 TypeScript。

为了论证,假设我们的错误是 No reducer provided for key "favourites"

对于导致此错误的测试,我们从该 reducer 的文件中导入了一个接口,这显然反过来运行该文件以生成导出。

我们的 favourites reducer 导入我们的 Redux store 以查询状态的另一位作为其切换案例之一的一部分。

出于某种原因,注释掉我们访问 Store.getState().someOtherReducersState 的行使错误消失了。

所以修复只是在测试文件中 jest.mock('../route/to/Store'); 导致错误输出。

我也有这个错误,原因和上面的评论一样,但我用更明智的方式修复了它:

将模块文件分成两个文件,一个用于 reducer,一个用于操作(而不是一个包含两者)

就我而言,事实证明其中一个模块存在循环依赖(它正在导入整个 state