430 Stimmen

Jasmin JavaScript Testing - toBe vs toEqual

Sagen wir, ich habe folgendes:

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

Beide der oben genannten Tests werden bestehen. Gibt es einen Unterschied zwischen toBe() und toEqual() bei der Auswertung von Zahlen? Wenn ja, wann sollte ich das eine und nicht das andere verwenden?

589voto

elreimundo Punkte 6026

Für primitive Typen (z.B. Zahlen, Booleans, Strings, etc.) gibt es keinen Unterschied zwischen toBe und toEqual; beide funktionieren für 5, true oder "the cake is a lie".

Um den Unterschied zwischen toBe und toEqual zu verstehen, stellen wir uns drei Objekte vor.

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

Bei einer strikten Vergleich (===) sind einige Dinge "gleich":

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

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

> c.foo === b.foo
true

Aber einige Dinge sind, obwohl sie "gleich" sind, nicht "identisch", da sie Objekte repräsentieren, die an verschiedenen Speicherorten existieren.

> b === c
false

Jasmin's toBe Matcher ist nichts anderes als ein Wrapper für einen strikten Vergleich auf Gleichheit

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

ist dasselbe wie

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

Vertraue aber nicht nur meinem Wort; siehe den Quellcode für toBe.

Aber b und c repräsentieren funktional äquivalente Objekte; sie sehen beide so aus

{ foo: { bar: 'baz' } }

Wäre es nicht großartig, wenn wir sagen könnten, dass b und c "gleich" sind, auch wenn sie nicht dasselbe Objekt repräsentieren?

Hier kommt toEqual ins Spiel, das "tiefgehende Gleichheit" prüft (d.h. eine rekursive Suche durch die Objekte durchführt, um zu bestimmen, ob die Werte ihrer Schlüssel äquivalent sind). Beide der folgenden Tests werden bestehen:

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

113voto

Adjit Punkte 9654

toBe() versus toEqual(): toEqual() überprüft die Äquivalenz. toBe() stellt hingegen sicher, dass es sich um dasselbe genaue Objekt handelt.

Ich würde sagen, benutze toBe() beim Vergleich von Werten und toEqual() beim Vergleich von Objekten.

Beim Vergleich von primitiven Typen werden toEqual() und toBe() das gleiche Ergebnis liefern. Beim Vergleich von Objekten ist toBe() ein strengerer Vergleich, und wenn es nicht dasselbe Objekt im Speicher ist, wird dies false zurückgeben. Also, wenn du sicherstellen möchtest, dass es dasselbe Objekt im Speicher ist, benutze toEqual() zum Vergleich von Objekten.

Schaue dir diesen Link für weitere Informationen an: http://evanhahn.com/how-do-i-jasmine/

Jetzt, wenn du den Unterschied zwischen toBe() und toEqual() bei Zahlen betrachtest, sollte es keinen Unterschied geben, solange dein Vergleich korrekt ist. 5 wird immer äquivalent zu 5 sein.

Ein schöner Ort, um damit herumzuspielen und verschiedene Ergebnisse zu sehen, ist hier

Update

Ein einfacher Weg, um toBe() und toEqual() zu verstehen, ist zu verstehen, was sie genau in JavaScript tun. Laut Jasmine API, die du hier findest:

toEqual() funktioniert für einfache Literale und Variablen und sollte für Objekte funktionieren

toBe() vergleicht mit ===

Im Grunde genommen bedeutet das, dass toEqual() und toBe() ähnlich dem JavaScript === Operator sind, außer dass toBe() auch überprüft, ob es sich um dasselbe genaue Objekt handelt, wie zum Beispiel hier objectOne === objectTwo //gibt false zurück. toEqual() hingegen gibt in dieser Situation true zurück.

Jetzt verstehst du zumindest, warum bei folgendem Beispiel:

var objectOne = {
    propertyOne: str,
    propertyTwo: num    
}

var objectTwo = {
    propertyOne: str,
    propertyTwo: num    
}

expect(objectOne).toBe(objectTwo); //gibt false zurück

Dies liegt daran, dass, wie in dieser Antwort auf eine andere, aber ähnliche Frage erwähnt wird, der === Operator tatsächlich bedeutet, dass beide Operanden auf dasselbe Objekt verweisen oder im Fall von Werttypen den gleichen Wert haben.

36voto

Tharaka Punkte 2295

Um das Jasmine-GitHub-Projekt zu zitieren,

expect(x).toEqual(y); vergleicht Objekte oder Primitiven x und y und gibt einen Erfolg zurück, wenn sie äquivalent sind

expect(x).toBe(y); vergleicht Objekte oder Primitiven x und y und gibt einen Erfolg zurück, wenn sie dasselbe Objekt sind

15voto

Tamlyn Punkte 20164

Ein Blick auf den Jasmine-Quellcode wirft mehr Licht auf das Thema.

toBe ist sehr einfach und verwendet einfach den Identitäts-/Striktheitsoperator, ===:

  function(actual, expected) {
    return {
      pass: actual === expected
    };
  }

toEqual dagegen ist fast 150 Zeilen lang und hat eine spezielle Behandlung für eingebaute Objekte wie String, Number, Boolean, Date, Error, Element und RegExp. Für andere Objekte vergleicht es rekursiv Eigenschaften.

Dies unterscheidet sich sehr vom Verhalten des Gleichheitsoperators, ==. Zum Beispiel:

var simpleObject = {foo: 'bar'};
expect(simpleObject).toEqual({foo: 'bar'}); //true
simpleObject == {foo: 'bar'}; //false

var castableObject = {toString: function(){return 'bar'}};
expect(castableObject).toEqual('bar'); //false
castableObject == 'bar'; //true

3voto

BeingSuman Punkte 2563

toEqual() vergleicht Werte, wenn Primitive oder Inhalte wenn Objekte. toBe() vergleicht Referenzen.

Der folgende Code / Suite sollte selbsterklärend sein:

describe('Understanding toBe vs toEqual', () => {
  let obj1, obj2, obj3;

  beforeEach(() => {
    obj1 = {
      a: 1,
      b: 'some string',
      c: true
    };

    obj2 = {
      a: 1,
      b: 'some string',
      c: true
    };

    obj3 = obj1;
  });

  afterEach(() => {
    obj1 = null;
    obj2 = null;
    obj3 = null;
  });

  it('Obj1 === Obj2', () => {
    expect(obj1).toEqual(obj2);
  });

  it('Obj1 === Obj3', () => {
    expect(obj1).toEqual(obj3);
  });

  it('Obj1 !=> Obj2', () => {
    expect(obj1).not.toBe(obj2);
  });

  it('Obj1 ==> Obj3', () => {
    expect(obj1).toBe(obj3);
  });
});

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X