使用React测试工具与Jest时无法匹配两个空对象
toEqual断言匹配失败的问题 我之前也碰到过这种看起来完全匪夷所思的问题——明明控制台显示预期和接收的都是空对象{},Jest的expect(received).toEqual(expected)却偏说它们不相等。结合你是在测试Redux Saga的场景,大概率是这两个空对象并非看起来那么“一模一样”,下面给你分析原因和解决办法:
先搞清楚两个对象的真实差异
首先别被表面的{}迷惑,你可以在断言前加几行代码,打印出对象的完整信息,看看是不是有隐藏属性或者不同的原型链:
// 在断言前添加这些打印语句 console.log('接收的对象:', get); console.log('对象的可枚举键:', Object.keys(get)); console.log('对象的所有属性名:', Object.getOwnPropertyNames(get)); console.log('对象的原型:', Object.getPrototypeOf(get));
很多时候这种“看起来空”的对象,其实带有Redux Saga相关的不可枚举包装属性,或者原型链和普通空对象不一样,导致toEqual的深层比对失败。
针对性的解决办法
根据Redux Saga测试的常见场景,你可以试试下面几种方案:
- 断言对象无任何可枚举属性
如果你的预期就是对象为空,直接断言它的键数量为0比比对空对象更可靠:
expect(Object.keys(get)).toHaveLength(0);
- 使用
jest.isEqual手动验证
有时候Jest的toEqual在处理特殊对象时会有偏差,你可以用Jest内置的比对函数手动验证:
expect(jest.isEqual(get, {})).toBe(true);
检查Saga返回值的获取方式
如果get是通过Saga的select方法获取的状态,确认你在测试中是否正确mock了store,返回的是纯净的状态对象,而不是带有Saga上下文的包装结构。比如用redux-saga/testing-utils的runSaga时,确保provide的store返回的是正确的原始状态。断言对象原型符合预期
如果是原型链的问题,你可以额外断言对象的原型是普通对象的原型:
expect(Object.getPrototypeOf(get)).toBe(Object.prototype);
你遇到的错误日志
$ yarn test
yarn run v1.5.1
warning ....\package.json: No license field
$ react-scripts test --env=jsdom
FAIL src\saga\saga.test.js
● get new action value
expect(received).toEqual(expected)
Expected value to equal: {}
Received: {}
Difference:
- Expected
- Received
-Object {}- {}
at Object.<anonym...
内容的提问来源于stack exchange,提问作者Max Wolfen

