首页 文章

Jasmine JavaScript测试 - toBe vs toEqual

提问于
浏览
274

假设我有以下内容:

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

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

7 回答

  • 11

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

    要理解 toBetoEqual 之间的区别,让我们想象三个对象 .

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

    使用严格的比较( === ),有些东西是"the same":

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

    但有些东西,即使它们“相等”,也不是“相同的”,因为它们代表了生活在记忆中不同位置的物体 .

    > b === c
    false
    

    Jasmine的 toBe matcher只不过是一个严格的平等比较的包装器

    expect(a.foo).toBe(b.foo)
    

    是一样的

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

    不要只听我的话;见the source code for toBe .

    bc 代表功能相同的对象;他们俩看起来都像

    { foo: { bar: 'baz' } }
    

    如果我们可以说 bc 是"equal",即使它们不代表同一个对象,也不是很好吗?

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

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

    希望有助于澄清一些事情 .

  • 69

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

  • 1

    引用jasmine github项目,

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

  • 26

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

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

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

  • 396

    toEqual() 比较原始值或内容if的值对象 . 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);
      });
    });
    
  • 1

    注意事项:

    • toBe() 对待如Object.is()的比较 .

    • toEqual() 对待如 === 的比较 .

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

相关问题