230

Is there a way in jasmine.js to check if two arrays are equal, for example:

arr = [1, 2, 3]
expect(arr).toBe([1, 2, 3])
expect(arr).toEqual([1, 2, 3])

Neither seems to work.

JJJ
  • 32,902
  • 20
  • 89
  • 102
user2032804
  • 2,599
  • 2
  • 14
  • 12

4 Answers4

370

Just did the test and it works with toEqual

please find my test:

http://jsfiddle.net/7q9N7/3/

describe('toEqual', function() {
    it('passes if arrays are equal', function() {
        var arr = [1, 2, 3];
        expect(arr).toEqual([1, 2, 3]);
    });
});

Just for information:

toBe() versus toEqual(): toEqual() checks equivalence. toBe(), on the other hand, makes sure that they're the exact same object.

d-_-b
  • 21,536
  • 40
  • 150
  • 256
TheEwook
  • 11,037
  • 6
  • 36
  • 55
  • Hm, thanks, it seems that the problem is that the array I'm comparing to is modified, so it does something like arr = [1, 2, 3] arr['pop'] = function() { ... } expect(arr).toEquals([1, 2, 3]) – user2032804 Mar 30 '13 at 11:33
  • 2
    how to test if values are equal within epsilon? e.g., my test fails Expected [ -9, -6, 6, 3, 1.0000000000000004, 2 ] to equal [ -9, -6, 6, 3, 1, 2 ]. – morpheus Feb 21 '14 at 23:16
  • @morpheus - I've tried `toBeCloseTo(expected,2)` but it doesn't seem to work. – cod3monk3y Mar 01 '14 at 22:58
  • the second argument of toBeCloseTo is the # of decimal places it will compare upto. – morpheus Mar 02 '14 at 17:58
  • 1
    this falls back on "==" in javascript by default. This is just not safe since not only the actual values are compared, but the whole object. – Peter Nov 12 '14 at 11:00
2

You can compare an array like the below mentioned if the array has some values

it('should check if the array are equal', function() {
        var mockArr = [1, 2, 3];
        expect(mockArr ).toEqual([1, 2, 3]);
 });

But if the array that is returned from some function has more than 1 elements and all are zero then verify by using

expect(mockArray[0]).toBe(0);
Utkarsh Joshi
  • 141
  • 1
  • 3
-2

just for the record you can always compare using JSON.stringify

const arr = [1,2,3]; expect(JSON.stringify(arr)).toBe(JSON.stringify([1,2,3])); expect(JSON.stringify(arr)).toEqual(JSON.stringify([1,2,3]));

It's all meter of taste, this will also work for complex literal objects

Luca Borrione
  • 16,324
  • 8
  • 52
  • 66
Ohad Sadan
  • 877
  • 6
  • 15
  • why would we need a difference between toBe and toEqual then? – Luca Borrione Nov 20 '18 at 06:07
  • there is no difference , I just wante'd to let it look like the question – Ohad Sadan Nov 20 '18 at 08:57
  • There is a difference between toBe and toEqual the OP was unsure about. An answer should clarify things, rather than showing improper use. The accepted answer already contains it all, your answer potentially introduces more confusion showing how to force jasmine to work in a way that it's not intended to work. – Luca Borrione Nov 21 '18 at 06:59
-4

I had a similar issue where one of the arrays was modified. I was using it for $httpBackend, and the returned object from that was actually a $promise object containing the array (not an Array object).

You can create a jasmine matcher to match the array by creating a toBeArray function:

beforeEach(function() {
  'use strict';
  this.addMatchers({
    toBeArray: function(array) {
      this.message = function() {
        return "Expected " + angular.mock.dump(this.actual) + " to be array " + angular.mock.dump(array) + ".";
      };
      var arraysAreSame = function(x, y) {
         var arraysAreSame = true;
         for(var i; i < x.length; i++)
            if(x[i] !== y[i])
               arraysAreSame = false;
         return arraysAreSame;
      };
      return arraysAreSame(this.actual, array);
    }
  });
});

And then just use it in your tests like the other jasmine matchers:

it('should compare arrays properly', function() {
  var array1, array2;
  /* . . . */
  expect(array1[0]).toBe(array2[0]);
  expect(array1).toBeArray(array2);
});
antimatter
  • 3,240
  • 2
  • 23
  • 34
  • 2
    I'm getting TypeError: this.addMatchers is not a function – AndyTheEntity Aug 06 '15 at 13:15
  • 4
    The "arraysAreSame" function you have provided will give a false positive for the arrays `x=[1,2]`, `y=[1,2,3]` since it only checks the first `x.length` elements. You can fix this by checking `if (x.length !== y.length) { return false; }` beforehand. – warchinal Sep 02 '15 at 23:33
  • 1
    @AndyTheEntity "The addMatchers function is no longer on the spec (this) it is now on the global jasmine object." - see [Jasmine docs](http://jasmine.github.io/2.0/upgrading.html) – rwisch45 May 01 '16 at 10:46
  • `for (var i; ...)` => `x[undefined]`, `var arraysAreSame = function ... var arraysAreSame = true` :( – André Werlang Dec 06 '17 at 17:35
  • @warchinal funny, it also fails to catch `expect([1]).toBeArray([2])`. And also any other array really, because `undefined + 1 => NaN` – André Werlang Dec 06 '17 at 17:39
  • @AndréWerlang actually that's because `.toBeArray()` is a function that takes no arguments, and just tells you if (in your case) `[1]` is an array, which it is. I think you meant to do `expect([1]).toEqual([2])`, which would of course fail – warchinal Dec 07 '17 at 23:20
  • @warchinal no, that's not it. See my 2 previous comments, it's pretty obvious that `i` isn't initialized – André Werlang Dec 07 '17 at 23:43