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

Reduxsauce实现的Redux Store单元测试方案及报错解决

解决Reduxsauce环境下Redux动作及Store的单元测试问题

我来帮你一步步解决这个测试报错的问题,并且梳理清楚Reduxsauce场景下的正确测试方式。

首先解决当前的报错问题

你现在的测试代码里,import * as actions from '../../../redux/LanguageRedux'会把文件里所有导出的内容(包括你定义的reducer函数getLanguage)都加载到actions对象里。当你调用actions.getLanguage()时,实际上调用的是reducer函数,而不是createActions生成的action creator。这就导致了错误——reducer函数期望接收state和action两个参数,但你调用时没传,所以解构{}的时候就会报Cannot destructure 'undefined' or 'null'。

正确的导入方式应该是导入默认导出的Creators(也就是action creators集合):

import actions from '../../../redux/LanguageRedux'
import { LanguageTypes, INITIAL_STATE, reducer } from '../../../redux/LanguageRedux'

这样actions.getLanguage()和actions.setLanguage('zh')就会调用正确的action creator,而不是reducer函数。


接下来分模块编写测试

Reduxsauce的测试可以拆分为action creators测试、reducers测试、完整store测试三个部分,下面分别说明:

1. 测试Action Creators

我们需要验证action creators生成的action包含正确的type和payload:

describe('Language Action Creators', () => {
  it('should create an action to trigger getLanguage', () => {
    const expectedAction = { type: LanguageTypes.GET_LANGUAGE }
    expect(actions.getLanguage()).toEqual(expectedAction)
  })

  it('should create an action to set language with correct payload', () => {
    const testLang = 'zh'
    const expectedAction = { 
      type: LanguageTypes.SET_LANGUAGE,
      language: testLang 
    }
    expect(actions.setLanguage(testLang)).toEqual(expectedAction)
  })
})

2. 测试Reducers

有两种方式测试reducers,你可以根据需求选择:

方式1:单独测试单个reducer函数

直接调用reducer函数,传入初始状态和模拟的action,检查返回的新状态:

describe('Language Reducer Functions', () => {
  it('getLanguage should return unchanged state', () => {
    const newState = getLanguage(INITIAL_STATE, {})
    expect(newState).toEqual(INITIAL_STATE)
  })

  it('setLanguage should update language state correctly', () => {
    const testLang = 'fr'
    const newState = setLanguage(INITIAL_STATE, { language: testLang })
    expect(newState.language).toEqual(testLang)
  })
})

方式2:测试完整的reducer(推荐)

使用createReducer生成的完整reducer,传入不同的action,验证状态变化:

describe('Language Combined Reducer', () => {
  it('should return initial state when receiving unknown action', () => {
    expect(reducer(undefined, { type: 'UNKNOWN_ACTION' })).toEqual(INITIAL_STATE)
  })

  it('should update language when handling SET_LANGUAGE action', () => {
    const testLang = 'de'
    const action = actions.setLanguage(testLang)
    const newState = reducer(INITIAL_STATE, action)
    expect(newState.language).toEqual(testLang)
  })

  it('should keep state unchanged when handling GET_LANGUAGE action', () => {
    const action = actions.getLanguage()
    const newState = reducer(INITIAL_STATE, action)
    expect(newState).toEqual(INITIAL_STATE)
  })
})

3. 测试完整的Store

如果你想验证整个store的行为(包括reducer集成后的状态变化),可以创建测试store,dispatch动作后检查状态:

import configureStore from '../../../redux/CreateStore'
import rootReducer from '../../../redux/rootReducer' // 对应你合并reducers的文件

describe('Language Store', () => {
  let store

  beforeEach(() => {
    // 创建测试用的store,如果不需要saga可以传null替代rootSaga
    store = configureStore(rootReducer, null)
  })

  it('should initialize with default language "en"', () => {
    expect(store.getState().language.language).toEqual('en')
  })

  it('should update language when SET_LANGUAGE is dispatched', () => {
    store.dispatch(actions.setLanguage('ja'))
    expect(store.getState().language.language).toEqual('ja')
  })

  it('should not modify state when GET_LANGUAGE is dispatched', () => {
    const initialState = store.getState().language
    store.dispatch(actions.getLanguage())
    expect(store.getState().language).toEqual(initialState)
  })
})

关键注意点

  • 一定要区分action creators(Creators对象里的方法)和reducer函数:导入时不要混淆,否则就会出现你遇到的调用错误。
  • 测试reducer时,优先选择测试完整的createReducer生成的reducer,这样能验证action type和reducer的绑定是否正确。
  • 测试完整store时,要注意初始化store的方式和生产环境保持一致,确保测试结果和实际运行逻辑匹配。

内容的提问来源于stack exchange,提问作者Maverick

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:38:40