Jest文档内容如下:
toBe只是检查一个值是否符合预期。它使用===来检查严格的相等性。
对于toEqual
:
如果要检查两个对象是否具有相同的值,请使用.toEqual。这个匹配器递归地检查所有字段的相等性,而不是检查对象标识 - 这也称为“深度相等”。例如,toEqual和toBe在此测试套件中的行为不同,因此所有测试都通过了。
const x = { a: { b: 3 } };
const y = { a: { b: 3 } };
expect(x).toEqual(y);
expect(x).toBe(y);
在这种情况下,toEqual
通过但toBe
失败。我了解toEqual
通过,因为它执行深度相等的检查。为什么toBe
在这种情况下失败了?
此外,是否有使用toBe
和toEqual
的最佳做法(不仅在Jest中,还在其他测试框架中)?
答案 0 :(得分:21)
失败原因x
和y
是不同的实例,与(x === y) === false
中的不相同。对于使用toBe
的所有其他内容,您可以将toEqual
用于字符串,数字或布尔等原语。例如
x = 4
y = 4
x === y // true
x = 'someString'
y = 'someString'
x === y // true
即使是空物也不相等
x = {}
y = {}
x === y //false
答案 1 :(得分:5)
自Jest v23起,您也有toStrictEqual()
说明:https://jestjs.io/docs/en/expect#tostrictequalvalue
有一个ESLint plugin for Jest,其中包含强制执行toStrictEqual()
的规则:https://github.com/jest-community/eslint-plugin-jest/blob/master/docs/rules/prefer-strict-equal.md
npm install --save-dev eslint-plugin-jest
// .eslintrc.js
module.exports = {
extends: [
'plugin:jest/recommended'
],
rules: {
'jest/prefer-strict-equal': 'error'
}
}
答案 2 :(得分:5)
假设有两个同名球员,并且他们都获得了20分。
let player1 = {
name: "Amit",
score: 20,
}
let player2 = {
name: "Amit",
score: 20,
}
现在我有一个功能可以给我第一个玩家。
function getFirstPlayer(player1,player2){
return player1;
}
我将如何测试此功能?
# 1st way
expect(getFirstPlayer(player1,player2)).toBe(player1); // Passes
expect(getFirstPlayer(player1,player2)).not.toBe(player2); // Passes
# 2nd way
expect(getFirstPlayer(player1,player2)).toEqual(player1); // Pases
expect(getFirstPlayer(player1,player2)).not.toEqual(player2); // Fails
toBe
测试身份,toEqual
测试功能。因此,双胞胎孩子可以具有相同的功能,但他们的真实身份彼此不同。
此函数的设计方式应使用toBe
。
现在,我还有另一个功能可以提高玩家得分。
function addScore(player,scoreToAdd){
player.score += scoreToAdd;
}
我将如何测试此功能?
# 1st way
addScore(player1,20);
expect(player1).toBe({name:"Amit", score:40}); // Fails
# 2nd way
addScore(player1,20);
expect(player1).toEqual({name:"Amit", score:40}); // Passes
您是否注意到,在第一种方式中,我们在右侧传递了一个新的球员,例如实体。 player1
是否有与新创建实体相同的身份?不。因此,toBe
在这种情况下总是会失败。
第二种方式与toEqual
中一样,我们正在比较特征。 player1
和新创建的实体在这里具有相同的功能。
注意:在javascript中,诸如"Amit"
之类的原始值本身就是身份。所以
expect("Amit").toBe("Amit") // Passes
我已经为特殊情况写了这个答案,当您有了关于身份和功能的想法时,可以在您的方案中实现它。
答案 3 :(得分:1)
有人说.toBe()
与x === y
相同,但实际上略有不同。 Jest在进行Object.is(x, y)
时会使用expect(x).toBe(y)
。
除非您要验证值是否与参考相同(例如,检查某些内容是否正确深克隆时),否则应始终使用.toEqual()
。而且,即使在Deepclone示例中,我认为只执行expect(x === y).toEqual(true)
只是为了消除对您要执行的操作的任何混淆也是比较干净的。
您不应该期望别人知道toBe
和toEqual
之间的区别,甚至不要知道Object.is
的存在以及与===
的区别。为避免通信问题和测试问题,请始终使用.toEqual
,切勿使用.toBe
。