You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 00:48:13