Verificando a igualdade do objeto no Jasmine

87

Jasmine tem matchers toBee toEqual. Se eu tiver um objeto como este:

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

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

e tente comparar new Money(200, "USD")e o resultado da soma, esses matchers internos não funcionarão conforme o esperado. Consegui implementar uma solução alternativa com base em um equalsmétodo personalizado e em um matcher personalizado, mas parece funcionar muito.

Qual é a maneira padrão de comparar objetos no Jasmine?

Dan
fonte

Respostas:

174

Eu estava procurando a mesma coisa e encontrei uma maneira existente de fazer isso sem qualquer código personalizado ou matchers. Use toEqual().

lukas.pukenis
fonte
63

Se você deseja comparar objetos parciais, pode considerar:

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

originalhat
fonte
3

É o comportamento esperado, já que duas instâncias de um objeto não são iguais em 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

Para um teste limpo, você deve escrever seu próprio matcher que compare amounte currency:

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

Eu descobri que lodash _.isEqual é bom para isso

expect(_.isEqual(result, expectedResult)).toBeTruthy()
Alexander Poshtaruk
fonte
-4

Seu problema é com a veracidade. Você está tentando comparar duas instâncias diferentes de um objeto que é verdadeiro para igualdade regular (a == b), mas não verdadeiro para igualdade estrita (a === b). O comparador que jasmine usa é jasmine.Env.equals_ () que procura igualdade estrita.

Para realizar o que você precisa sem alterar seu código, você pode usar a igualdade regular verificando a veracidade com algo um pouco como o seguinte:

expect(money1.sum() == money2.sum()).toBeTruthy();
Baer
fonte
9
O que você disse ==e ===está completamente errado. Duas instâncias diferentes de um objeto com o mesmo conteúdo retornarão falso. Para quaisquer não primitivos ==e ===se comportem de forma idêntica. jsfiddle.net/9mrmyrs6
Juan Mendes
@JuanMendes confira a resposta de Andreas K. ... vocês estão dizendo duas coisas diferentes. Esta é uma diferença em criar um objeto em relação a um objeto literal?
pherris de
@pherris mmm .... sim, estamos dizendo coisas diferentes: estou dizendo que ao comparar não-primitivos, não importa se você usa ==ou ===, não há coerção envolvida. Andreas está dizendo que você pode criar um matcher personalizado. A última declaração sobre como corrigir esse problema é "correta", mas a explicação no primeiro parágrafo está simplesmente incorreta. jasmineirá verificar o conteúdo do objeto se você usar em toBe()vez deequals
Juan Mendes
a == bainda dará falso se ae bforem instâncias diferentes, você pode querer editar sua resposta
Louie Almeda