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

使用Jest测试Redux时如何在每个测试用例后重置store?

Redux测试用例状态冲突解决方案

核心原则

测试用例之间完全隔离是单元测试的基本要求,Redux测试出现状态串扰的核心原因是多个测试复用了同一个store实例,没有在测试间隔清除上一个测试的状态变更。

主流实现方案

方案1:每个测试生成独立store(社区首推)

不需要改造任何生产代码,完全从测试侧解决问题,是最通用的方案:

  • 封装独立的测试用store创建函数,支持传入自定义初始状态
  • 借助Jest的beforeEach钩子,在每个测试运行前都生成全新的store实例,所有测试的dispatch、状态读取操作都作用在这个新实例上

示例代码:

import { configureStore } from '@reduxjs/toolkit'
import rootReducer from '你的rootReducer路径'

// 封装测试store生成逻辑
const createTestStore = (preloadedState = {}) => {
  return configureStore({
    reducer: rootReducer,
    preloadedState
  })
}

let store
// 每个测试启动前都初始化新store
beforeEach(() => {
  store = createTestStore()
})

// 测试用例直接使用store即可
test('添加用户', () => {
  store.dispatch(addUser({ id: 1, name: 'test' }))
  expect(store.getState().users.length).toBe(1)
})

test('添加并删除用户', () => {
  store.dispatch(addUser({ id: 1, name: 'test' }))
  store.dispatch(deleteUser(1))
  expect(store.getState().users.length).toBe(0)
})

方案2:添加重置store的action(适合必须复用单store的场景)

如果你的测试场景有特殊要求必须复用同一个store实例,可以通过改造root reducer实现状态重置:

  • 给root reducer增加RESET_STORE的action处理逻辑,触发时返回应用初始状态
  • 借助Jest的afterEach钩子,在每个测试结束后触发重置action

示例代码:

// 改造root reducer
import { combineReducers } from '@reduxjs/toolkit'
import usersReducer from './usersSlice'

const appReducer = combineReducers({
  users: usersReducer,
  // 其他业务reducer
})

export const rootReducer = (state, action) => {
  if (action.type === 'global/resetStore') {
    // 传入undefined作为state,会让所有子reducer返回自身初始状态
    return appReducer(undefined, action)
  }
  return appReducer(state, action)
}

// 测试文件中添加重置逻辑
afterEach(() => {
  store.dispatch({ type: 'global/resetStore' })
})

注意事项

  • 优先选择方案1,不需要侵入生产代码,也不会出现重置逻辑遗漏导致的状态残留问题
  • 禁止在测试文件顶层初始化全局唯一的store实例,所有store的生成都要放在钩子函数或者单个测试内部

内容的提问来源于stack exchange,提问作者Amir M. Mohamadi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.29 12:39:00