测试时Redux报Expected the reducer to be a function异常,但Reducer确为函数
This is a tricky, seemingly contradictory issue—let’s break down the most likely causes and fix steps based on your scenario:
First, let’s recap your problem to align:
I’m getting the error
Expected the reducer to be a functionduring testing, even though my reducer is definitely a function. Oddly,src/App.test.jspasses without issues, console logs confirm the reducer is afunction, butsrc/actions/querySelector.test.jsfails with this error, with the call stack pointing to Redux’screateStoremethod.
Top Causes & Fixes
1. Mismatched Import/Export in the Failing Test File
This is the most common culprit for this kind of inconsistent behavior. Double-check how you’re importing the reducer in querySelector.test.js:
- If your reducer uses default export:
Make sure your test imports it correctly:// reducers/myReducer.js export default function myReducer(state, action) { /* ... */ }// Correct import myReducer from '../reducers/myReducer'; // Wrong (will return undefined) import { myReducer } from '../reducers/myReducer'; - If your reducer uses named export:
Use named imports in the test:// reducers/myReducer.js export function myReducer(state, action) { /* ... */ }// Correct import { myReducer } from '../reducers/myReducer'; // Wrong (will return undefined) import myReducer from '../reducers/myReducer';
Quick debug step: Add this line right before creating your store in the test file:
console.log('Imported reducer type:', typeof myReducer); console.log('Imported reducer value:', myReducer);
If this logs undefined or anything other than function, your import is broken.
2. Test Runner Module Caching Issues
Tools like Jest cache module imports by default, which can lead to stale references if another test modifies or mocks the reducer. To fix this:
Add a reset for modules in the failing test file:
beforeEach(() => { jest.resetModules(); });
This ensures each test in the suite gets a fresh import of your reducer, avoiding cached, incorrect references.
3. Invalid Store Creation Arguments
Double-check how you’re calling createStore in querySelector.test.js:
- Make sure you’re passing the reducer function directly (or a combined reducer from
combineReducers), not an object or other invalid value.// Wrong (passes an object instead of a reducer function) const store = createStore({ myReducer }); // Correct (passes the reducer function) const store = createStore(myReducer); // Correct (using combineReducers) import { combineReducers } from 'redux'; const rootReducer = combineReducers({ myReducer }); const store = createStore(rootReducer);
4. Dynamic Import Race Conditions
If your reducer is loaded dynamically with import(), the test might try to create the store before the Promise resolves, passing a Promise instead of a function. Ensure you await the dynamic import before creating the store:
// Correct const { default: myReducer } = await import('../reducers/myReducer'); const store = createStore(myReducer);
Final Recommendation
Start with the import check and debug console log—this will immediately tell you if the reducer is actually being loaded correctly in the failing test. If that checks out, reset the module cache next. These two steps resolve 90% of cases like this.
内容的提问来源于stack exchange,提问作者Neil

