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
)
我用 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
.
祝你好运!
要合并 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
)