93

Jasmine has built-in matchers toBe and toEqual. If I have an object like this:

function Money(amount, currency){
    this.amount = amount;
    this.currency = currency;

    this.sum = function (money){
        return new Money(200, "USD");
    }
}

and try to compare new Money(200, "USD") and the result of sum, these built-in matchers will not work as expected. I have managed to implement a work-around based on a custom equals method and custom matcher, but it just seems to much work.

What is the standard way to compare objects in Jasmine?

4

6 回答 6

185

I was looking for the same thing and found an existing way to do so without any custom code or matchers. Use toEqual().

于 2013-07-05T08:45:01.827 回答
69

If you're looking to compare partial objects, you might consider:

describe("jasmine.objectContaining", function() {
  var foo;

  beforeEach(function() {
    foo = {
      a: 1,
      b: 2,
      bar: "baz"
    };
  });

  it("matches objects with the expect key/value pairs", function() {
    expect(foo).toEqual(jasmine.objectContaining({
      bar: "baz"
    }));
  });
});

cf. jasmine.github.io/partial-matching

于 2015-02-11T19:50:57.223 回答
3

Its the expected behavior, as two instances of an object are not the same in JavaScript.

function Money(amount, currency){
  this.amount = amount;
  this.currency = currency;

  this.sum = function (money){
    return new Money(200, "USD");
  }
}

var a = new Money(200, "USD")
var b = a.sum();

console.log(a == b) //false
console.log(a === b) //false

For a clean test you should write your own matcher that compares amount and currency:

beforeEach(function() {
  this.addMatchers({
    sameAmountOfMoney: function(expected) {
      return this.actual.currency == expected.currency && this.actual.amount == expected.amount;
    }
  });
});
于 2013-05-06T19:36:20.900 回答
2

I found that lodash _.isEqual is good for that

expect(_.isEqual(result, expectedResult)).toBeTruthy()
于 2019-09-25T07:40:11.780 回答
0

I managed to compare two objects without any custom code via :

import { deepStrictEqual } from 'assert'
// ...
expect(deepStrictEqual.bind(null, objectA, objectB)).not.toThrow()

note : assert is a native node module, no need to install anything here

于 2021-06-21T14:03:53.183 回答
-5

Your problem is with truthyness. You are trying to compare two different instances of an object which is true for regular equality ( a == b ) but not true for strict equality ( a === b). The comparator that jasmine uses is jasmine.Env.equals_() which looks for strict equality.

To accomplish what you need without changing your code you can use the regular equality by checking for truthyness with something a little like the following:

expect(money1.sum() == money2.sum()).toBeTruthy();
于 2013-05-09T05:46:08.380 回答