Search code examples
javascriptjasmine

Jasmine JavaScript Testing - toBe vs toEqual


Let's say I have the following:

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

Both of the above tests will pass. Is there a difference between toBe() and toEqual() when it comes to evaluating numbers? If so, when I should use one and not the other?


Solution

  • For primitive types (e.g. numbers, booleans, strings, etc.), there is no difference between toBe and toEqual; either one will work for 5, true, or "the cake is a lie".

    To understand the difference between toBe and toEqual, let's imagine three objects.

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

    Using a strict comparison (===), some things are "the same":

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

    But some things, even though they are "equal", are not "the same", since they represent objects that live in different locations in memory.

    > b === c
    false
    

    Jasmine's toBe matcher is nothing more than a wrapper for a strict equality comparison

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

    is the same thing as

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

    Don't just take my word for it; see the source code for toBe.

    But b and c represent functionally equivalent objects; they both look like

    { foo: { bar: 'baz' } }
    

    Wouldn't it be great if we could say that b and c are "equal" even if they don't represent the same object?

    Enter toEqual, which checks "deep equality" (i.e. does a recursive search through the objects to determine whether the values for their keys are equivalent). Both of the following tests will pass:

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