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

如何比较两个Redux Store状态?Reducer测试中的状态差异校验

如何在Redux Reducer测试中校验仅指定字段变更

这问题我之前写Redux测试时也踩过坑,核心就是要先深拷贝旧状态,再精准对比新旧状态的差异。下面给你具体的实现方案:

第一步:深拷贝旧状态

Redux的状态是不可变对象,但直接赋值会拿到引用,所以必须用深拷贝来保存dispatch前的状态。推荐两种方式:

方式1:使用Lodash的cloneDeep(推荐复杂场景)

如果项目里已经有lodash,直接用最可靠的深拷贝方法:

import _ from 'lodash';

it('dispatch change', () => {
  // 深拷贝旧状态
  const oldState = _.cloneDeep(store.getState());
  
  store.dispatch(updateStoredCustomerDetails({ email: 'blabla@blabla.com' }));
  const newState = store.getState();
  
  // 后续校验逻辑...
});

方式2:原生JSON序列化(简单场景)

如果状态里没有函数、Symbol等JSON不支持的类型,可以用原生方法:

it('dispatch change', () => {
  const oldState = JSON.parse(JSON.stringify(store.getState()));
  
  store.dispatch(updateStoredCustomerDetails({ email: 'blabla@blabla.com' }));
  const newState = store.getState();
  
  // 后续校验逻辑...
});

第二步:校验仅邮箱字段变更

接下来要确保只有email字段变化,其余状态完全一致,这里有两种直观的校验方式:

方式1:拆分对象对比(最清晰)

把新旧状态中的email字段剔除,对比剩下的部分是否完全相等,同时单独校验邮箱的值:

it('dispatch change', () => {
  const oldState = _.cloneDeep(store.getState());
  
  store.dispatch(updateStoredCustomerDetails({ email: 'blabla@blabla.com' }));
  const newState = store.getState();
  
  // 1. 确认邮箱确实更新为目标值
  expect(newState.customer.email).toBe('blabla@blabla.com');
  
  // 2. 剔除邮箱字段后,其余状态完全一致
  const { email: _, ...oldCustomerWithoutEmail } = oldState.customer;
  const { email: __, ...newCustomerWithoutEmail } = newState.customer;
  expect(newCustomerWithoutEmail).toEqual(oldCustomerWithoutEmail);
  
  // 如果整个store除了customer的email外都不变,还可以校验根状态的其他部分
  const { customer: oldCustomer, ...oldRootWithoutCustomer } = oldState;
  const { customer: newCustomer, ...newRootWithoutCustomer } = newState;
  expect(newRootWithoutCustomer).toEqual(oldRootWithoutCustomer);
});

方式2:自定义差异对比函数

写一个小工具函数,找出两个对象的所有差异,然后期望差异只有email字段:

// 工具函数:获取两个对象的差异(支持嵌套对象的浅层对比)
function getObjectDiff(objA, objB) {
  return Object.keys(objA).reduce((diff, key) => {
    if (JSON.stringify(objA[key]) === JSON.stringify(objB[key])) {
      return diff;
    }
    return { ...diff, [key]: objB[key] };
  }, {});
}

it('dispatch change', () => {
  const oldState = _.cloneDeep(store.getState());
  
  store.dispatch(updateStoredCustomerDetails({ email: 'blabla@blabla.com' }));
  const newState = store.getState();
  
  // 获取customer对象的差异
  const customerDiff = getObjectDiff(oldState.customer, newState.customer);
  
  // 期望差异仅包含email字段,且值正确
  expect(customerDiff).toEqual({ email: 'blabla@blabla.com' });
});

额外建议

  • 可以把深拷贝和差异对比的逻辑封装成测试工具函数,复用在其他Reducer测试中
  • 避免用console.log调试,直接用测试框架的断言来验证结果,这样测试更可靠

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 03:44:03