OP bakış açısına tamamen katılıyorum. Assert.assertFalse(expected.equals(actual))
eşitsizliği ifade etmenin doğal bir yolu değildir.
Ama daha o başka iddia ediyorum Assert.assertEquals()
, Assert.assertNotEquals()
eserlerini fakat test aslında iddia ve onaylama işlemi başarısız olarak / debug anlamaya ne belgeye kullanıcı dostu değildir.
Yani evet JUnit 4.11 ve JUnit 5 sağlar Assert.assertNotEquals()
( Assertions.assertNotEquals()
JUnit 5'te) ama gerçekten onları kullanmaktan kaçının.
Alternatif olarak, bir nesnenin durumunu iddia etmek için, genel olarak, nesne durumuna kolayca giren, iddiaların amacını açıkça belgeleyen ve onaylama hatasının nedenini anlamak için çok kullanıcı dostu olan bir eşleştirici API'sini kullanıyorum.
İşte bir örnek. Yöntemi
test etmek istediğim bir Animal sınıfım createWithNewNameAndAge()
olduğunu, adını ve yaşını değiştirerek ama en sevdiği yemeği koruyarak yeni bir Animal nesnesi oluşturan bir yöntem olduğunu varsayalım . Orijinalin ve yeni nesnelerin farklı olduğunu iddia etmek için
kullandığımı varsayalım Assert.assertNotEquals()
.
Kusurlu bir uygulaması olan Animal sınıfı createWithNewNameAndAge()
:
public class Animal {
private String name;
private int age;
private String favoriteFood;
public Animal(String name, int age, String favoriteFood) {
this.name = name;
this.age = age;
this.favoriteFood = favoriteFood;
}
// Flawed implementation : use this.name and this.age to create the
// new Animal instead of using the name and age parameters
public Animal createWithNewNameAndAge(String name, int age) {
return new Animal(this.name, this.age, this.favoriteFood);
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public String getFavoriteFood() {
return favoriteFood;
}
@Override
public String toString() {
return "Animal [name=" + name + ", age=" + age + ", favoriteFood=" + favoriteFood + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((favoriteFood == null) ? 0 : favoriteFood.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Animal)) return false;
Animal other = (Animal) obj;
return age == other.age && favoriteFood.equals(other.favoriteFood) &&
name.equals(other.name);
}
}
JUnit 4.11+ (veya JUnit 5) hem test çalıştırıcısı hem de onaylama aracı olarak
@Test
void assertListNotEquals_JUnit_way() {
Animal scoubi = new Animal("scoubi", 10, "hay");
Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
Assert.assertNotEquals(scoubi, littleScoubi);
}
Test beklendiği gibi başarısız oluyor, ancak geliştiriciye sağlanan neden gerçekten yardımcı olmuyor. Sadece değerlerin farklı olması gerektiğini ve toString()
gerçek Animal
parametrede çağrılan sonucu çıkardığını söylüyor :
java.lang.AssertionError: Değerler farklı olmalıdır. Gerçek: Hayvan
[ad = scoubi, yaş = 10, favoriGıda = saman]
org.junit.Assert.fail'da (Assert.java:88)
Tamam, nesneler eşit değil. Ama sorun nerede?
Test edilen yöntemde hangi alan doğru şekilde değerlendirilmiyor? Bir ? İki ? Hepsi ?
Bunu keşfetmek için createWithNewNameAndAge()
, test API'sı bizim için beklenen ile kazanılan arasındaki farkı yaparsa çok daha kolay olurken uygulamada bir hata ayıklayıcı kullanmanız / bir hata ayıklayıcı kullanmanız gerekir.
Test koşucusu olarak JUnit 4.11 ve onaylama aracı olarak bir test Matcher API
Burada aynı test senaryosu ancak durumun iddiasını yapmak için AssertJ (mükemmel bir test eşleştirici API) kullanır Animal
:
import org.assertj.core.api.Assertions;
@Test
void assertListNotEquals_AssertJ() {
Animal scoubi = new Animal("scoubi", 10, "hay");
Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
Assertions.assertThat(littleScoubi)
.extracting(Animal::getName, Animal::getAge, Animal::getFavoriteFood)
.containsExactly("little scoubi", 1, "hay");
}
Elbette test hala başarısız oluyor, ancak bu kez neden açıkça belirtildi:
java.lang.AssertionError:
bekleniyor:
<["scoubi", 10, "saman"]>
tam olarak (ve aynı sırada) içermesi:
<["küçük scoubi", 1, "saman"]>
ancak bazı öğeler bulunamadı:
<["küçük scoubi", 1]>
ve diğerleri beklenmiyordu:
<["scoubi", 10]>
junit5.MyTest.assertListNotEquals_AssertJ (MyTest.java:26)
Animal::getName, Animal::getAge, Animal::getFavoriteFood
Döndürülen Hayvanın değerleri için şu değere sahip olmayı beklediğimizi okuyabiliriz :
"little scoubi", 1, "hay"
ancak şu değerleri elde ettik:
"scoubi", 10, "hay"
Bu yüzden nerede araştırma yapacağımızı biliyoruz: name
ve age
doğru değerlendirilmiyor. Ek olarak, hay
iddiası iddiasındaki değeri belirtme gerçeği Animal::getFavoriteFood()
aynı zamanda iade edilenin daha hassas bir şekilde iddia edilmesine izin verir Animal
. Nesnelerin bazı özellikler için aynı olmasını değil, her özellik için olması gerekmez.
Kesinlikle, bir eşleştirici API kullanmak çok daha net ve esnektir.