Vérification de l'égalité des objets dans Jasmine

85

Jasmine a des matchers intégrés toBeet toEqual. Si j'ai un objet comme celui-ci:

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

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

et essayez de comparer new Money(200, "USD")et le résultat de la somme, ces matchers intégrés ne fonctionneront pas comme prévu. J'ai réussi à implémenter une solution de contournement basée sur une equalsméthode personnalisée et un matcher personnalisé, mais cela semble juste beaucoup de travail.

Quelle est la manière standard de comparer des objets dans Jasmine?

Dan
la source

Réponses:

172

Je cherchais la même chose et j'ai trouvé un moyen existant de le faire sans aucun code personnalisé ni correspondance. Utilisez toEqual().

lukas.pukenis
la source
63

Si vous cherchez à comparer des objets partiels, vous pouvez envisager:

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

obfk
la source
3

C'est le comportement attendu, car deux instances d'un objet ne sont pas les mêmes en 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

Pour un test propre, vous devez écrire votre propre matcher qui compare amountet currency:

beforeEach(function() {
  this.addMatchers({
    sameAmountOfMoney: function(expected) {
      return this.actual.currency == expected.currency && this.actual.amount == expected.amount;
    }
  });
});
Andreas Köberle
la source
2

J'ai trouvé que lodash _.isEqual est bon pour ça

expect(_.isEqual(result, expectedResult)).toBeTruthy()
Alexandre Poshtaruk
la source
-4

Votre problème est avec la vérité. Vous essayez de comparer deux instances différentes d'un objet qui est vrai pour l'égalité régulière (a == b) mais pas vrai pour l'égalité stricte (a === b). Le comparateur utilisé par jasmine est jasmine.Env.equals_ () qui recherche une égalité stricte.

Pour accomplir ce dont vous avez besoin sans changer votre code, vous pouvez utiliser l'égalité régulière en vérifiant la véracité avec quelque chose d'un peu comme ce qui suit:

expect(money1.sum() == money2.sum()).toBeTruthy();
Baer
la source
9
Ce que vous avez dit ==et ===est complètement faux. Deux instances différentes d'un objet avec le même contenu renverront toutes deux false. Pour tous les non-primitifs, ==et ===se comportent de la même manière. jsfiddle.net/9mrmyrs6
Juan Mendes
@JuanMendes regarde la réponse d'Andreas K. ... vous dites deux choses différentes. Est-ce une différence dans la création d'un objet par rapport à un objet littéral?
pherris
@pherris mmm .... oui, nous disons des choses différentes: je dis que lorsque vous comparez des non-primitifs, peu importe que vous utilisiez ==ou ===, il n'y a pas de coercition. Andreas dit que vous pouvez créer un matcher personnalisé. La dernière déclaration sur la façon de résoudre ce problème est "correcte" mais l'explication dans le premier paragraphe est tout simplement incorrecte. jasminevérifiera réellement le contenu de l'objet si vous utilisez à la toBe()place deequals
Juan Mendes
a == bdonnera toujours false si aet bsont des instances différentes, vous voudrez peut-être modifier votre réponse
Louie Almeda