ChatGPT解决这个技术问题 Extra ChatGPT

Jasmine JavaScript 测试 - toBe vs toEqual

假设我有以下内容:

var myNumber = 5;
expect(myNumber).toBe(5);
expect(myNumber).toEqual(5);

上述两项测试都将通过。在评估数字时,toBe()toEqual() 有区别吗?如果是这样,我什么时候应该使用一个而不是另一个?

简而言之:比较原语时两者之间没有区别;对于对象-> toEqual() 将按键/值-内容进行比较; toBe() 将按对象引用进行比较。

N
Nil

对于原始类型(例如数字、布尔值、字符串等),toBetoEqual 没有区别;任何一个都适用于 5true"the cake is a lie"

为了理解 toBetoEqual 之间的区别,让我们想象三个对象。

var a = { bar: 'baz' },
    b = { foo: a },
    c = { foo: a };

使用严格比较 (===),有些事情是“相同的”:

> b.foo.bar === c.foo.bar
true

> b.foo.bar === a.bar
true

> c.foo === b.foo
true

但是有些东西,即使它们是“相等的”,也不是“相同的”,因为它们代表了存在于内存中不同位置的对象。

> b === c
false

Jasmine 的 toBe 匹配器只不过是严格相等比较的包装器

expect(c.foo).toBe(b.foo)

是一样的

expect(c.foo === b.foo).toBe(true)

不要只相信我的话;见the source code for toBe

但是 bc 表示功能上等价的对象;他们看起来都像

{ foo: { bar: 'baz' } }

如果我们可以说 bc 是“相等的”,即使它们不代表同一个对象,那不是很好吗?

输入 toEqual,它检查“深度相等”(即对对象进行递归搜索以确定其键的值是否相等)。以下两个测试都将通过:

expect(b).not.toBe(c);
expect(b).toEqual(c);

希望这有助于澄清一些事情。


“对于原始类型(例如数字、布尔值、字符串等),toBe 和 toEqual 之间没有区别”——事实证明这并不完全正确。 expect(0).toBe(-0) 将通过,但 expect(0).toEqual(-0) 将失败。
tl;dr - toBe 使用严格相等 - 通过引用比较,toEqual 使用属性等价。建议将 toEqual 用于基元
那么我们应该将哪一个用于原语,为什么? Drenai,你为什么推荐toEqual?
@PatrickSzalapski 我只能猜测 Denai 的推理,但 toEqual 对平等(0 != -0"hi" = new String("hi") 等)更加谨慎,所以我建议使用 toEqual 专门除非您实际上担心参考等效性。在此处查看 toEqualeq 方法中所做的所有检查:github.com/jasmine/jasmine/blob/master/src/core/matchers/…
我认为在比较原语时最好使用 toBe 以节省在 toEqual 中完成的开销。
C
Community

toBe()toEqual()toEqual() 检查等价性。另一方面,toBe() 确保它们是完全相同的对象。

我会说比较值时使用 toBe(),比较对象时使用 toEqual()

比较原始类型时,toEqual()toBe() 将产生相同的结果。比较对象时,toBe() 是更严格的比较,如果它不是内存中完全相同的对象,则返回 false。因此,除非您想确保它在内存中是完全相同的对象,否则请使用 toEqual() 来比较对象。

查看此链接了解更多信息:http://evanhahn.com/how-do-i-jasmine/

现在查看 toBe()toEqual() 在数字方面的区别时,只要您的比较是正确的,就不应该有任何区别。 5 将始终等同于 5

here

更新

查看 toBe()toEqual() 的一种简单方法是了解它们在 JavaScript 中的确切作用。根据 Jasmine API,找到 here

toEqual() 适用于简单的文字和变量,并且应该适用于对象 toBe() 与 === 比较

本质上说的是 toEqual()toBe() 是类似的 Javascripts === 运算符,除了 toBe() 还检查以确保它是完全相同的对象,在 objectOne === objectTwo //returns false 下面的示例中也是如此。但是,在这种情况下,toEqual() 将返回 true。

现在,您至少可以理解为什么给出:

var objectOne = {
    propertyOne: str,
    propertyTwo: num    
}

var objectTwo = {
    propertyOne: str,
    propertyTwo: num    
}

expect(objectOne).toBe(objectTwo); //returns false

这是因为,如 this answer to a different, but similar question, 中所述,=== 运算符实际上意味着两个操作数都引用同一个对象,或者在值类型的情况下,具有相同的值。


这避免了回答问题。您通过说 toEqual() 检查等价性 来解释 toEqual() 的作用,但下一个明显的问题是好的,那么“等价”是什么意思?用于确定“等价”的算法,或者至少是 toEqual()toBe() 的行为不同的情况的示例,将使这更有用。
这不仅没有回答问题,而且是错误toEqual 应该用于对象之间的深度比较,而不是 toBejsfiddle.net/bBL9P/67
人们似乎并没有费心去测试他们所说的是否正确。 toBe 和 toEqual 似乎都是严格的比较。测试它...所以在我的测试中我还没有找到不同之处。例如:var f = 1; var g = "1" expect(f == g).toEqual(true);//true expect(f).toEqual(g);//false expect(f).toBe(g);//false
这是完全错误的。 toEqual 根本不== 相同。
阅读上面的评论。 expect(1).toEqual('1') 失败,而 1 == '1' 为真。 toEqual== 无关。它与 === 类似,只是它将以类似于按值比较的方式比较对象。
T
Tharaka

引用 jasmine github 项目,

期望(x).toEqual(y);比较对象或原语 x 和 y,如果它们是等价的则通过 expect(x).toBe(y);比较对象或原语 x 和 y,如果它们是同一个对象,则通过


T
Tamlyn

查看 Jasmine 源代码可以更清楚地了解这个问题。

toBe 非常简单,只使用身份/严格相等运算符 ===

  function(actual, expected) {
    return {
      pass: actual === expected
    };
  }

另一方面,toEqual 有近 150 行长,对 StringNumberBooleanDateErrorElementRegExp 等内置对象有特殊处理.对于其他对象,它递归地比较属性。

这与相等运算符 == 的行为非常不同。例如:

var simpleObject = {foo: 'bar'};
expect(simpleObject).toEqual({foo: 'bar'}); //true
simpleObject == {foo: 'bar'}; //false

var castableObject = {toString: function(){return 'bar'}};
expect(castableObject).toEqual('bar'); //false
castableObject == 'bar'; //true

B
BeingSuman

toEqual() 如果是 Primitive,则比较值,如果是 Objects,则比较内容。 toBe() 比较参考。

以下代码/套件应该是不言自明的:

describe('Understanding toBe vs toEqual', () => {
  let obj1, obj2, obj3;

  beforeEach(() => {
    obj1 = {
      a: 1,
      b: 'some string',
      c: true
    };

    obj2 = {
      a: 1,
      b: 'some string',
      c: true
    };

    obj3 = obj1;
  });

  afterEach(() => {
    obj1 = null;
    obj2 = null;
    obj3 = null;
  });

  it('Obj1 === Obj2', () => {
    expect(obj1).toEqual(obj2);
  });

  it('Obj1 === Obj3', () => {
    expect(obj1).toEqual(obj3);
  });

  it('Obj1 !=> Obj2', () => {
    expect(obj1).not.toBe(obj2);
  });

  it('Obj1 ==> Obj3', () => {
    expect(obj1).toBe(obj3);
  });
});

f
feyzullahyildiz

我认为 toEqual 正在检查深度相等,toBe 是 2 个变量的相同引用

  it('test me', () => {
    expect([] === []).toEqual(false) // true
    expect([] == []).toEqual(false) // true

    expect([]).toEqual([]); // true // deep check
    expect([]).toBe([]); // false
  })

J
Jared Tomaszewski

认为有人可能喜欢通过(带注释的)示例进行解释:

下面,如果我的 deepClone() 函数正常工作,则测试(如“it()”调用中所述)将成功:

describe('deepClone() array copy', ()=>{
    let source:any = {}
    let clone:any = source
    beforeAll(()=>{
        source.a = [1,'string literal',{x:10, obj:{y:4}}]
        clone = Utils.deepClone(source) // THE CLONING ACT TO BE TESTED - lets see it it does it right.
    })
    it('should create a clone which has unique identity, but equal values as the source object',()=>{
        expect(source !== clone).toBe(true) // If we have different object instances...
        expect(source).not.toBe(clone) // <= synonymous to the above. Will fail if: you remove the '.not', and if: the two being compared are indeed different objects.
        expect(source).toEqual(clone) // ...that hold same values, all tests will succeed.
    })
})

当然,这不是我的 deepClone() 的完整测试套件,因为我没有在这里测试数组中的对象字面量(以及嵌套在其中的对象字面量)是否也具有不同的标识但相同的值。