【问题标题】:Jasmine JavaScript Testing - toBe vs toEqualJasmine JavaScript 测试 - toBe vs toEqual
【发布时间】:2014-04-20 05:12:34
【问题描述】:

假设我有以下内容:

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

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

【问题讨论】:

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

标签: javascript jasmine


【解决方案1】:

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根本不==相同。
  • 阅读上面的 cmets。 expect(1).toEqual('1') 失败,而 1 == '1' 为真。 toEqual== 无关。它类似于===,只是它会以类似于按值比较的方式比较对象。
【解决方案2】:

引用jasmine github项目,

expect(x).toEqual(y); 比较对象或原语 x 和 y 和 如果它们相等则通过

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

【讨论】:

    【解决方案3】:

    对于原始类型(例如数字、布尔值、字符串等),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 中完成的开销。
    【解决方案4】:

    查看 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
    

    【讨论】:

      【解决方案5】:

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

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

      【讨论】:

        【解决方案6】:

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

        【讨论】:

          【解决方案7】:

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

            it('test me', () => {
              expect([] === []).toEqual(false) // true
              expect([] == []).toEqual(false) // true
          
              expect([]).toEqual([]); // true // deep check
              expect([]).toBe([]); // false
            })
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2019-12-30
            • 2017-12-24
            • 2017-12-28
            • 1970-01-01
            • 2015-12-13
            • 2013-11-13
            • 2014-01-23
            • 1970-01-01
            相关资源
            最近更新 更多