Java'nın assertEquals yöntemi güvenilir midir?


199

==İkisini karşılaştırırken bazı sorunları olduğunu biliyorum Strings. Bu String.equals()daha iyi bir yaklaşım gibi görünüyor . JUnit testi yapıyorum ve benim eğimim kullanmak assertEquals(str1, str2). İki Dizenin aynı içeriği içerdiğini iddia etmenin güvenilir bir yolu var mı? Kullanırdım assertTrue(str1.equals(str2)), ama sonra beklenen ve gerçek değerlerin başarısızlıkla sonuçlandığını görmekten yararlanamazsınız.

İlgili bir notta, herkesin sorunları açık bir şekilde açıklayan bir sayfaya veya konuya bağlantısı var str1 == str2mı?


1
Emin değilseniz kodu veya Javadoc'u okuyabilirsiniz. BTW test etmek istiyorsanız assertSame ile aynı nesnedir.
Peter Lawrey

2
Str1 ve str2 boşsa, assertEquals () doğrudur, ancak assertTrue (str1.equals (str2)) bir istisna atar. İlk örnek ayrıca str1 ve str2 içeriği gibi yararlı bir hata mesajı yazdırır, ikincisi yapmaz.
Peter Lawrey

Yanıtlar:


274

Sen gerektiğini hep kullanmak .equals()karşılaştırırken StringsJava.

JUnit .equals()yöntemde eşitliği belirlemek için yöntemi çağırır assertEquals(Object o1, Object o2).

Yani, kesinlikle kullanmak güvenlidir assertEquals(string1, string2). (Çünkü Strings Objects)

İşte== ve arasındaki bazı farklarla ilgili harika bir Stackoverflow sorusuna bir bağlantı.equals() .


12
Her iki dize de boşsa IIRC assertEquals () başarılı olur. İstediğiniz bu değilse assertNotNull () öğesini de arayın.
finnw

10
Eğer == için teste istiyorsanız ayrıca, sen assertSame () çağırabilir
james

7
Her zaman söylemezdim ; bazen dizgiler için bile referans eşitliği istenir.
Karu

30

assertEqualsequalskarşılaştırma yöntemini kullanır . Operatörü assertSamekullanan farklı bir iddia var ==.

Neden ==dizelerle kullanılmaması gerektiğini anlamak için ne yaptığını anlamalısınız ==: bir kimlik kontrolü yapar. Olduğunu, a == bçekler olmadığını görmek için ave bbakın aynı nesne . Dilde yerleşiktir ve davranışı farklı sınıflar tarafından değiştirilemez. equalsYöntem olup, diğer taraftan, sınıflar geçersiz kılınabilir. Varsayılan davranışı ( Objectsınıfta) ==işleci kullanarak bir kimlik denetimi yapmak olsa da , dahil olmak üzere birçok sınıf Stringbir "denklik" denetimi yapmak yerine geçersiz kılar. Durumunda String, yerine, denetimi ave baynı nesneyi,a.equals(b) atıfta bulundukları nesnelerin her ikisi de tam olarak aynı karakterleri içeren dizeler olup olmadığını kontrol eder.

Analoji zamanı: Her Stringnesnenin üzerinde bir şey yazılı bir kağıt parçası olduğunu hayal edin . Diyelim ki üzerlerinde "Foo" yazılı iki kağıt parçası ve üzerine "Bar" yazılı başka bir kağıt var. İlk iki kağıdı alıp ==karşılaştırmak için kullanırsam geri döner falseçünkü aslında "bunlar aynı kağıt parçası mı?" Kağıda yazılanlara bile bakmasına gerek yok. İki kağıt verdiğim gerçeği (aynı kağıt yerine iki kez) geri döneceği anlamına geliyor false. equalsBununla birlikte, kullanırsam , equalsyöntem iki kağıdı okuyacak ve aynı şeyi ("Foo") söylediklerini görecek ve böylece geri dönecektir true.

Dizelerle kafa karıştırıcı olan bit, Java'nın "stajyer" Dizeler kavramına sahip olması ve kodunuzdaki herhangi bir dize değişmezinde otomatik olarak (etkin bir şekilde) gerçekleştirilmesidir. Bu, kodunuzda iki eşdeğer dize değişmezine sahipseniz (farklı sınıflarda olsalar bile), aslında her ikisinin de aynı Stringnesneyi ifade edeceği anlamına gelir . Bu, ==operatörün truebeklediğinden daha sık dönmesini sağlar .


"Yani, a == b, a ve b'nin aynı nesne olup olmadığını kontrol eder." Teknik olarak a ve b'nin aynı nesneye REFER olup olmadığını kontrol eder, çünkü a ve b referanslardır. Çok yanlış değilsem.
bob

@ user1903064 doğru. İlkel olmayan değişkenler yalnızca Java'da referanslar içerebileceğinden, bunlar hakkında konuşurken fazladan dolaylı atlama düzeyini atlamak yaygındır, ancak bu durumda daha açık olmanın yararlı olduğunu kabul ediyorum. Cevabı güncelledim. Önerin için teşekkürler!
Laurence Gonsalves

7

Özetle - aynı karakterleri içeren ancak farklı nesneler (farklı bellek konumlarında) olan iki String nesnesine sahip olabilirsiniz. == işleci, iki başvurunun aynı nesneyi (bellek konumu) işaret ettiğini kontrol eder, ancak equals () yöntemi karakterlerin aynı olup olmadığını kontrol eder.

Genellikle, iki Dizenin aynı bellek konumuna işaret edip etmediklerini değil aynı karakterleri içerip içermediğini kontrol etmekle ilgilenirsiniz.


4
public class StringEqualityTest extends TestCase {
    public void testEquality() throws Exception {
        String a = "abcde";
        String b = new String(a);
        assertTrue(a.equals(b));
        assertFalse(a == b);
        assertEquals(a, b);
    }
}

3

Evet, her zaman test için kullanılır. Test çerçevesinin bunlar gibi karşılaştırmalar için .equals () kullanması çok olasıdır.

Aşağıda "string eşitlik hatası" nı açıklayan bir link bulunmaktadır. Temel olarak, Java'daki dizeler nesnelerdir ve nesne eşitliğini karşılaştırdığınızda, genellikle içeriğe göre değil, bellek adresine göre karşılaştırılırlar. Bu nedenle, içeriği aynı olsa bile iki dize aynı adresi işgal etmez, bu nedenle yazdırıldıklarında aynı görünseler bile doğru şekilde eşleşmezler.

http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/


3

JUnit assertEquals(obj1, obj2)gerçekten çağırıyor obj1.equals(obj2).

Ayrıca , kaçınmaya çalıştığınız şey de assertSame(obj1, obj2)var obj1 == obj2(yani, bunu doğrular obj1ve aynı örneğe obj2başvuruyor ).

Yani sen iyisin.


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.