Jest中'toBe'和'toEqual'有什么区别?

时间:2017-07-19 15:30:36

标签: testing jestjs

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在这种情况下失败了?

此外,是否有使用toBetoEqual的最佳做法(不仅在Jest中,还在其他测试框架中)?

4 个答案:

答案 0 :(得分:21)

失败原因xy是不同的实例,与(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)只是为了消除对您要执行的操作的任何混淆也是比较干净的。

您不应该期望别人知道toBetoEqual之间的区别,甚至不要知道Object.is的存在以及与===的区别。为避免通信问题和测试问题,请始终使用.toEqual,切勿使用.toBe