假设我有以下内容:

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

以上两个测试都将通过。在计算数字时,toBe()和toEqual()之间有区别吗?如果是的话,什么时候我应该使用其中一种而不是另一种?


当前回答

toEqual()比较的是原语的值,还是对象的内容。 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);
  });
});

其他回答

toEqual()比较的是原语的值,还是对象的内容。 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);
  });
});

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

toBe非常简单,只使用恒等/严格等式运算符===:

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

另一方面,toEqual有近150行长,并且对内置对象有特殊处理,比如String、Number、Boolean、Date、Error、Element和RegExp。对于其他对象,它递归地比较属性。

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

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

对于基本类型(例如数字、布尔值、字符串等),toBe和toEqual之间没有区别;要么一个人挣5美元,这是真的,要么“蛋糕是个谎言”。

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

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)

不要只相信我的话;参见toBe的源代码。

但b和c表示功能等效的对象;它们看起来都像

{ foo: { bar: 'baz' } }

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

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

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

引用jasmine github项目,

期望(x) .toEqual (y);比较对象或原语x和y和 如果它们相等,则通过 期望(x) .toBe (y);比较对象或原语x和y并传递 如果它们是同一个物体

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

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

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

更多信息请点击这个链接:http://evanhahn.com/how-do-i-jasmine/

现在,当观察toBe()和toEqual()在数字方面的差异时,只要你的比较是正确的,就不应该有任何差异。5总是等于5。

这里是一个很好的地方,可以玩这个,看看不同的结果

更新

观察toBe()和toEqual()的一个简单方法是理解它们在JavaScript中的具体功能。根据茉莉API,在这里找到:

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

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

现在,你至少可以理解为什么:

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

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

预计(objectOne .toBe (objectTwo));/ /返回假

这是因为,正如对另一个不同但类似的问题的回答中所述,===操作符实际上意味着两个操作数引用相同的对象,或者对于值类型来说,具有相同的值。