Jasmine JavaScript测试 - toBe vs toEqual

时间:2014-03-14 18:29:23

标签: javascript jasmine

假设我有以下内容:

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

上述两项测试都将通过。在评估数字时,toBe()toEqual()之间是否存在差异?如果是这样,我应该使用一个而不是另一个?

8 个答案:

答案 0 :(得分:405)

对于原始类型(例如数字,布尔值,字符串等),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(a.foo).toBe(b.foo)

相同
expect(a.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);

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

答案 1 :(得分:71)

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,中所述,===运算符实际上意味着两个操作数引用同一个对象,或者在值类型的情况下,具有相同的值。

答案 2 :(得分:26)

引用jasmine github项目,

  

expect(x).toEqual(y);比较对象或基元x和y和   如果相等则通过

     

expect(x).toBe(y);比较对象或基元x和y并传递   如果它们是同一个对象

答案 3 :(得分:12)

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

toBe非常简单,只使用identity / strict相等运算符===

  function(actual, expected) {
    return {
      pass: actual === expected
    };
  }
另一方面,

toEqual近150行,对StringNumberBoolean,{{1}等内置对象进行了特殊处理},DateErrorElement。对于其他对象,它递归地比较属性。

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

==

答案 4 :(得分:1)

认为有人可能会通过(带注释的)示例解释:

下面,如果我的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()的完整测试套件,因为我没有在这里测试过数组中的对象文字(以及嵌套在其中的对象文字)是否具有不同的标识但是具有相同的值。 / p>

答案 5 :(得分:1)

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);
  });
});

答案 6 :(得分:1)

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

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

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

答案 7 :(得分:-1)

注意事项:

  • toBe()会像Object.is()那样对待比较。
  • toEqual()会像===那样对待比较。

这就是原始类型toBetoEqual在测试相等性时没有太大区别的原因,但对于像对象这样的引用类型,你宁愿使用toEqual来测试为了平等。