Redux-Toolkit开发Reddit克隆应用遇TypeError: middleware is not a function
问题:Redux-Toolkit测试触发TypeError: middleware is not a function
我用Redux-Toolkit开发了一个Reddit克隆应用,测试环节触发了TypeError: middleware is not a function错误。试过YouTube教程里的方案、按照Redux-Toolkit文档调整中间件,甚至把测试框架从Jest换成Vitest并修改配置,问题仍未解决。
测试文件
import React from 'react' import { render, screen } from '@testing-library/react' import configureStore from 'redux-mock-store' import { Provider } from 'react-redux' import Comments from '../Comments' import { MemoryRouter } from 'react-router-dom' import thunk from 'redux-thunk' const middleware = [thunk] const mockStore = configureStore(middleware) const initialState = { comments: { comments: { data: { children: [ {data: {id: 1, body: 'comment 1', author: 'author 1'}}, {data: {id: 2, body: 'comment 2', author: 'author 2'}} ] }, }, selectedComments: 'selected comment', showButton: 'hide comments' } } test('should render the comment count in comment component', () => { var storeE = mockStore(initialState) render( <Provider store={storeE}> <MemoryRouter> <Comments/> </MemoryRouter> </Provider> ) const commentCount = screen.getByText('comment 1') expect(commentCount('2 comments')).toBeVisible(); })
Comments组件
import { Box, Typography, Button } from '@mui/material' import React, { useEffect, useRef } from 'react' import { Link } from 'react-router-dom' import {useDispatch, useSelector} from 'react-redux' import { getCommentsData } from '../API/Api' import { setButton } from './CommentsSlice' const Comments = () => { const dispatch = useDispatch() const commentsData = useSelector(state => state.comments.comments?.data?.children) const selectedComment = useSelector(state => state.comments.selectedComments) const selectedBtn = useSelector(state => state.comments.showButton) const commentsList = useRef() useEffect(() => { dispatch(getCommentsData(selectedComment)) window.scrollTo({ top: 0, behavior: 'smooth' }) }, [dispatch, selectedComment]) const hideComment = () => { if(selectedBtn === 'show comments'){ dispatch(setButton('hide comments')) } if(selectedBtn === 'hide comments'){ dispatch(setButton('show comments')) } } const commentItems = commentsData && commentsData.length > 0 ? ( commentsData.map((item, idx) => ( <Box key={item.data.id} sx={{color: 'white', display:'flex', justifyContent: 'center', alignItems:'center', flexDirection: 'column', borderBottom: '1px solid #3d3d3d', marginX: '70px', marginBottom:'50px'}}> <Typography gutterBottom>Comment {idx + 1}</Typography> <Box sx={{marginTop:'20px',marginBottom:'20px', textAlign:'center'}}> <Typography>{item.data.body}</Typography> <Typography sx={{marginTop:'10px'}}>Author: {item.data.author}</Typography> </Box> </Box> )) ):(<Box>No Comments</Box>) return ( <Box sx={{width: '100%', marginTop:'20px', marginLeft:'20px'}}> <Box> <Link to='/' onClick={hideComment}> <Button>Back to posts</Button> </Link> </Box> <Box ref={commentsList}> {commentItems} </Box> </Box> ) } export default Comments
Comments Slice
import { createSlice } from "@reduxjs/toolkit"; export const CommentsSLice = createSlice({ name: 'comments', initialState: { comments: [], selectedComments: '', showButton: 'show comments' }, reducers:{ setComments(state, action){ state.comments = action.payload }, setSelectedComment(state, action){ state.selectedComments = action.payload }, setButton(action, state){ state.showButton = action.payload } } }) export const { setComments, setSelectedComment, setButton } = CommentsSLice.actions export default CommentsSLice.reducer
解决方案
1. 修复redux-mock-store调用方式(核心错误)
redux-mock-store v4+版本的configureStore需要传入配置对象,而非直接传中间件数组。修改测试文件代码:
// 原代码 const middleware = [thunk] const mockStore = configureStore(middleware) // 修改后 const mockStore = configureStore({ middleware: [thunk] })
同时确保redux-thunk导入正确,v2.x及以上版本推荐命名导入:
// 原导入 import thunk from 'redux-thunk' // 修改为 import { thunk } from 'redux-thunk'
2. 修正Comments Slice的reducer参数顺序
setButton reducer的参数顺序写反了,Redux reducer标准顺序是(state, action),修改Slice代码:
// 原代码 setButton(action, state){ state.showButton = action.payload } // 修改后 setButton(state, action){ state.showButton = action.payload }
3. 修复测试断言逻辑
原断言代码存在逻辑错误,screen.getByText返回DOM元素,不能作为函数调用。调整为:
// 原代码 const commentCount = screen.getByText('comment 1') expect(commentCount('2 comments')).toBeVisible(); // 修改后(验证评论数量显示) const commentCountElement = screen.getByText('2 comments') expect(commentCountElement).toBeVisible(); // 或验证渲染的评论数量 const commentElements = screen.getAllByText(/Comment \d+/); expect(commentElements).toHaveLength(2);
内容的提问来源于stack exchange,提问作者Stefke
相关产品推荐
相关产品推荐

