基本减速器可能会改变应用程序状态

basic reducer possibly mutating app state

我正在使用 Redux 扩展运算符来希望将状态保持为不可变对象。

但是,我设法使最简单的单元测试失败。

我认为错误可能与不可变有关,但我没有正确使用展开运算符吗?

这是我的单元测试:

describe('app logic', () => {
  it('initialises app', () => {
    const newState = reducer(INITIAL_STATE, {type: "NEXT"})
    const expectState = {
      start: true,
      render_component: null,
      requests: {},
      results: {},
    }
    console.log('newState', newState)
    console.log('expected state', expectState)
    expect(newState).to.equal(expectState)
  })
})

这是我的减速器

export const INITIAL_STATE = {
  start: false,
  render_component: null,
  requests: {},
  results: {}
}

export const next = (state) => {
  if (state === INITIAL_STATE) {
    return {
      ...state,
      start: true,
    }
  }
  return state
}

export function reducer(state = INITIAL_STATE, action) {
  switch (action.type) {
    case 'NEXT':
      return next(state)
    default:
      return state
  }
}

我打印了这两个对象,它们看起来一样。 我收到错误:

1) 应用程序逻辑初始化应用程序:

  AssertionError: expected { Object (start, render_component, ...) } to equal { Object (start, render_component, ...) }

不确定您使用的是哪个测试库,但通常使用 .equal 之类的名称来测试严格相等性 ( === ),这意味着(至少在对象的情况下)被比较的两个事物实际上必须引用完全相同的对象。所以,例如,

const original = { a: 1 }; // creates a new object, assign it
const testMe = { a: 1 }; // creates another new object, assign it
console.log( original === testMe )   // false

计算结果为 false,因为虽然对象具有相同的 content,但它们并不引用完全相同的对象。它们是独立的、独立创建的对象,但恰好具有相同的内容。与

相比
const original = {a: 1}; // create a new object
const testMe = original;  // create another reference to the same object
console.log( original === testMe );  // true

所以当你return

return {
  ...state,
  start: true,
}

您正在创建并 returning 一个新对象,因此它自然可以 引用您创建并分配给变量名的同一个对象 expectedState.

如果您感兴趣的不是严格相等,而只是两个对象中的内容相同,则存在除.equal之外的其他方法,通常命名为deep (因为他们深入 objects/arrays/whatever 来检查值是否相同)。

Chai.js 在他们的文档中有 expect(x).to.equal(y)expect(x).to.deep.equal(y) 的例子:http://chaijs.com/api/bdd/#method_equal

您的测试库可能具有非常相似的语法,如果不完全相同的话。