Yasemin JavaScript Testi - TOBE - TOEQUAL


349

Diyelim ki aşağıdakilere sahibim:

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

Yukarıdaki testlerin her ikisi de geçecektir. Sayıları değerlendirme arasında toBe()ve toEqual()ne zaman bir fark var ? Eğer öyleyse, ne zaman diğerini kullanmam gerekir?


kısaca: ilkelleri karşılaştırırken ikisi arasında fark yok; nesneler için -> toEqual()anahtar / değer içeriğine göre karşılaştırır; toBe()nesne referansı ile karşılaştırır.
Andre Elrico

Yanıtlar:


489

İlkel tipler için (örn. Sayılar, booleans, teller, vb.), toBeVe arasında bir fark yoktur toEqual; ikisinden biri için çalışacak 5, trueya da "the cake is a lie".

Arasındaki farkı anlamak için toBeve toEqual, en üç nesne düşünelim.

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

Katı bir karşılaştırma ( ===) kullanarak , bazı şeyler "aynı" olur:

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

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

> c.foo === b.foo
true

Ancak bazı şeyler, "eşit" olmalarına rağmen, "aynı" değildir, çünkü bunlar bellekteki farklı yerlerde yaşayan nesneleri temsil eder.

> b === c
false

Jasmine'in toBemaççısı sıkı bir eşitlik karşılaştırması için bir sarıcıdan başka bir şey değil

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

ile aynı şey

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

Sadece benim sözüme güvenme; bkz Tobe için kaynak kodunu .

Ancak bve cişlevsel olarak eşdeğer nesneleri temsil eder; ikisi de benziyor

{ foo: { bar: 'baz' } }

Bunu söyleyebilirsek bve caynı nesneyi temsil etmese bile "eşit" olmamız harika olmaz mıydı ?

toEqual"Derin eşitliği" kontrol eden Enter (örn. Anahtarlarının değerlerinin eşdeğer olup olmadığını belirlemek için nesneler arasında yinelemeli arama yapar). Aşağıdaki testlerin her ikisi de geçecektir:

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

Umarım bazı şeyleri açıklığa kavuşturur.


17
"İlkel tipler için (örn. Sayılar, booleanlar, karakter dizileri, vb.), ToBe ve toEqual arasında bir fark yoktur" - çünkü bu tamamen doğru değildir. expect(0).toBe(-0)geçecek ama expect(0).toEqual(-0)başarısız olacak.
mgol

11
tl; dr - toBekatı eşitlik kullanır - referans ile karşılaştır, toEqualözellik eşdeğerini kullanır. toEqualİlkel için kullanılması önerilir
Drenai

1
Peki ilkel için hangisini kullanmalıyız, neden? Drenai, neden tavsiye etmelisin?
Patrick Szalapski

@PatrickSzalapski Sadece Denai gerekçesinde tahmin, ama toEqualeşitlik (hakkında çok daha dikkatli olduğunu 0 != -0, "hi" = new String("hi")kullanıyorum tavsiye ederim bu yüzden, vs.) toEqual münhasıran aslında referans denklik endişe sürece. Tüm kontrolleri gör toEqualyapar eq: Burada yöntemin github.com/jasmine/jasmine/blob/master/src/core/matchers/...
Nehir

ToEqual'de yapılan ek yükü kurtarmak için ilkelleri karşılaştırırken toBe kullanmak daha iyi olur.
GarfieldKlon

81

toBe()karşı toEqual(): toEqual()denkliği kontrol eder. toBe()diğer yandan, aynı nesne olduklarından emin olur.

toBe()Değerleri karşılaştırırken ve toEqual()nesneleri karşılaştırırken kullan diyebilirim .

Zaman ilkel türde karşılaştırılması toEqual()ve toBe()aynı sonucu verecektir. Nesneleri toBe()karşılaştırırken, daha katı bir karşılaştırmadır ve bellekteki tam olarak aynı nesne değilse bu false değerini döndürür. Bu nedenle, bellekteki tam olarak aynı nesne olduğundan emin olmak istemiyorsanız, toEqual()nesneleri karşılaştırmak için kullanın .

Daha fazla bilgi için bu bağlantıya göz atın: http://evanhahn.com/how-do-i-jasmine/

Şimdi, sayılar arasındaki toBe()ve toEqual()sayıları arasındaki farka baktığınızda, karşılaştırmanız doğru olduğu sürece herhangi bir fark olmamalıdır. 5her zaman eşdeğer olacaktır 5.

Farklı sonuçlar görmek için bununla oynamak için güzel bir yer burada

Güncelleme

Bakmanın kolay bir yolu toBe()ve toEqual()JavaScript'te tam olarak ne yaptıklarını anlamaktır. Jasmine API'ye göre, burada bulundu :

toEqual () basit değişmez değerler ve değişkenler için çalışır ve nesneler için çalışmalıdır

toBe () ile karşılaştırır ===

Aslında söyleyen toEqual()ve toBe()benzer Javascripts ===operatörü dışında toBe()ne de aynı örnek olduğundan emin olmak için kontrol ediyor, aşağıdaki örnekte objectOne === objectTwo //returns falsede. Ancak, toEqual()bu durumda doğru dönecektir.

Şimdi, en azından neden verildiğinde anlayabilirsiniz:

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

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

expect(objectOne).toBe(objectTwo); //returns false

Bunun nedeni, farklı ama benzer bir sorunun cevabında belirtildiği gibi , ===operatörün aslında her iki işlenenin de aynı nesneye başvurduğu veya değer türlerinde aynı değere sahip olduğu anlamına gelir.


4
Bu, soruyu cevaplamaktan kaçınır. Bunun denkliği kontroltoEqual() ettiğini söyleyerek neyi açıklıyorsunuz , ama açık olan bir sonraki soru tamam, peki "eşdeğer" ne demektir? "Eşdeğerliği" belirlemek için kullanılan algoritmanın açıklaması ya da en azından davranışının ve farklılık gösterdiği durumların örnekleri bunu daha kullanışlı hale getirecektir. toEqual()toEqual()toBe()
Mark Amery

8
Bu sadece soruyu cevaplamakla kalmaz, aynı zamanda yanlıştır . toEqualnesneler arasında derin karşılaştırma için kullanılmalıdır toBe. jsfiddle.net/bBL9P/67
Lloyd Banks

3
İnsanların söylediklerinin doğru olup olmadığını test etmek için uğraşmadıkları anlaşılıyor. Hem TOE hem TOEQUAL katı karşılaştırmalar gibi görünüyor. Test edin ... Yani benim testimde henüz bir fark bulamıyorum. örneğin: var f = 1; var g = "1" bekle (f == g) .toEqual (true); // doğru bekle (f) .toEqual (g); // yanlış bekle (f) .toBe (g); // yanlış
kullanıcı1809104

6
Bu tamamen yanlış. toEqualolan hiç değil aynı ==.
meagar

6
Yukarıdaki yorumları okuyun. expect(1).toEqual('1')başarısız olsa da 1 == '1', doğrudur. toEqualhiçbir ilgisi yok ==. Sanki ===o yan değere kıyasla benzer bir şekilde nesneleri karşılaştırmak hariç.
meagar

33

Yasemin github projesini alıntılamak için,

expect(x).toEqual(y); x ve y nesnelerini veya ilkellerini karşılaştırır ve eşdeğerlerse geçer

expect(x).toBe(y);x ve y nesnelerini veya ilkellerini karşılaştırır ve aynı nesne ise geçer


14

Yasemin kaynak koduna bakıldığında konuya daha fazla ışık tutuyor.

toBeçok basittir ve sadece kimlik / katı eşitlik operatörünü kullanır ===:

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

toEqualÖte yandan, yaklaşık 150 satır uzunluğundadır ve benzeri nesneler inşa için özel işlem vardır String, Number, Boolean, Date, Error, Elementve RegExp. Diğer nesneler için özyinelemeli olarak özellikleri karşılaştırır.

Bu eşitlik operatörünün davranışından çok farklıdır ==. Örneğin:

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

2

toEqual()İlkel ise değerleri veya Nesneler ise içeriği karşılaştırır. toBe()referansları karşılaştırır.

Aşağıdaki kod / paket kendini açıklayıcı olmalıdır:

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);
  });
});

1

Birinin (açıklamalı) örnekle açıklama yapmaktan hoşlanabileceğini düşündüm:

Aşağıda, deepClone () işlevim işini doğru yaparsa, test ('it ()' çağrısında açıklandığı gibi) başarılı olur:

describe('deepClone() array copy', ()=>{
    let source:any = {}
    let clone:any = source
    beforeAll(()=>{
        source.a = [1,'string literal',{x:10, obj:{y:4}}]
        clone = Utils.deepClone(source) // THE CLONING ACT TO BE TESTED - lets see it it does it right.
    })
    it('should create a clone which has unique identity, but equal values as the source object',()=>{
        expect(source !== clone).toBe(true) // If we have different object instances...
        expect(source).not.toBe(clone) // <= synonymous to the above. Will fail if: you remove the '.not', and if: the two being compared are indeed different objects.
        expect(source).toEqual(clone) // ...that hold same values, all tests will succeed.
    })
})

Tabii ki bu benim deepClone () için tam bir test paketi değil, ben burada dizideki değişmez nesne (ve orada iç içe) de farklı bir kimlik ama aynı değerleri olup olmadığını test etmedi.


0

BenceEqual derin eşit kontrol ediyor, toBe 2 değişkenin aynı referansı

  it('test me', () => {
    expect([] === []).toEqual(false) // true
    expect([] == []).toEqual(false) // true

    expect([]).toEqual([]); // true // deep check
    expect([]).toBe([]); // false
  })

-2

Dikkat edilmesi gereken noktalar:

  • toBe()karşılaştırmaları nasıl Object.is()yapar gibi davranır .
  • toEqual()karşılaştırmaları nasıl ===yapar gibi davranır .

Bu yüzden ilkel tipler için toBeve toEqualeşitliği test ederken çok fazla farkları yoktur, ancak nesneler gibi referans türleri toEqualiçin, eşitliği test etmek için kullanmayı tercih edersiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.