JUnit がassertNotEquals メソッドを提供しないのはなぜですか?
質問
JUnit 4 が提供する理由を知っている人はいますか? assertEquals(foo,bar)
だがしかし assertNotEqual(foo,bar)
方法?
それは提供します assertNotSame
(対応する assertSame
) そして assertFalse
(対応する assertTrue
)なので、わざわざ含めなかったのは奇妙に思えます assertNotEqual
.
ところで、JUnit アドオンが私が探しているメソッドを提供していることはわかっています。ただ好奇心から聞いているだけです。
解決
私はあなたが新しい assertThat()
のスタイルを主張する使用をお勧めしたい、そのことができます簡単に否定のすべての種類を説明し、自動的にアサーションが失敗した場合に期待される内容の説明と、何を得たの構築ます:
assertThat(objectUnderTest, is(not(someOtherObject)));
assertThat(objectUnderTest, not(someOtherObject));
assertThat(objectUnderTest, not(equalTo(someOtherObject)));
すべての3つのオプションは等価で、あなたが最も読みやすい見つけるいずれかを選択します。
メソッドの単純な名前を使用します(この緊張構文が機能するよう)するには、これらの輸入が必要になります:
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
他のヒント
があります assertNotEquals
JUnit 4.11 では: https://github.com/junit-team/junit/blob/master/doc/ReleaseNotes4.11.md#improvements-to-assert-and-assume
import static org.junit.Assert.assertNotEquals;
私は同じだろう。アサートのAPIは非常に対称ではありません。オブジェクトが同じであるかどうかを試験するため、それはassertSame
とassertNotSame
を提供します。
もちろん、書くには長すぎるではありません。
assertFalse(foo.equals(bar));
このようなアサーションでは、出力の唯一の有益な部分は、残念ながらテストメソッドの名前であるため、説明メッセージを別々に形成する必要があります
String msg = "Expected <" + foo + "> to be unequal to <" + bar +">";
assertFalse(msg, foo.equals(bar));
これは、もちろん、あなた自身のassertNotEqual
をロールバックする方が良いということなので、面倒です。幸いにも、将来的にそれは多分のJUnitの一部になります:のJUnit問題22 の
私はassertNotEqualの不在は確かに非対称であるとJUnitが少し少ない学習可能になると主張していると思います。メソッドを追加するとき、これはきちんとしたケースであることに留意し、少なくとも私にとっては、APIの複雑さを軽減します:対称性は、大きなスペースを支配することができます。 私の推測では、不作為の理由は、メソッドの呼び出しの数が少なすぎる人がいるということかもしれないということです。しかし、私もassertFalseが存在していなかった時間を覚えています。したがって、私はそれは難しいものではないことを考えると、この方法は、最終的に追加されるかもしれないことを肯定期待を持っています。私は、多くの回避策、でもエレガントなものがあることを認めていても。
私はかなり遅れてこのパーティーに来ているが、私は、フォームが見つかっています:
static void assertTrue(java.lang.String message, boolean condition)
最も「等しくない」場合のために働くようにすることができます。
int status = doSomething() ; // expected to return 123
assertTrue("doSomething() returned unexpected status", status != 123 ) ;
私はjUnit4.12を使用して、Javaの8環境でのJUnitに取り組んでいます。
私のために:コンパイラは、私が
を使用した場合でも、メソッドassertNotEqualsを見つけることができませんでした
import org.junit.Assert;
だから私はassertNotEquals("addb", string);
を
する
Assert.assertNotEquals("addb", string);
を変更
assertNotEqual
が認識されないに関する問題に直面しているのであれば、それはあなたの問題を解決する必要がありAssert.assertNotEquals(,);
するように変更し、
の人々は()assertNotEqualsを望んでいたことは明白な理由は、最初の本格的なオブジェクトに変換することなく、組み込みコマンドを比較することであった。
冗長な例:
....
assertThat(1, not(equalTo(Integer.valueOf(winningBidderId))));
....
対。
assertNotEqual(1, winningBidderId);
EclipseはデフォルトでJUnitの4.11が含まれていない悲しいので、あなたは冗長である必要があります。
私は「1」Integer.valueOf(に包まれる必要があるとは思わない)が、私が新たに.NETから返されていますので、注意点は、私の正しさにはカウントされません。
これは、試験報告書は、アサーションの失敗のための差分を表示しますかつてのように負の表明ではなく、assertFalseためHamcrestを使用することをお勧めします。
あなたがassertFalseを使用する場合は、、あなただけのレポートでは、アサーションの失敗を取得します。すなわち、障害の原因についての情報が失われます。
私は、ビューのOPポイントと完全に同意します。 Assert.assertFalse(expected.equals(actual))
は不平等を表現する自然な方法ではありません。
しかし、私はAssert.assertEquals()
、Assert.assertNotEquals()
の作品よりも、さらにそれを主張するが、テストは実際にアサートし、アサーションが失敗したとして/デバッグを理解するために何を文書化し、ユーザーフレンドリーではないでしょう。
そうですJUnitの4.11とJUnit 5は(JUnitの5にAssert.assertNotEquals()
)Assertions.assertNotEquals()
を提供しますが、私は実際にそれらを使用することは避けてください。
は、別の方法として、私は一般的に容易オブジェクトの状態に食い込むマッチャーAPI、明確にその文書の主張の意図を使用し、オブジェクトの状態を主張するために、それは、アサーションの失敗の原因を理解することは非常にユーザーフレンドリーです。
ここでは一例である。
私はcreateWithNewNameAndAge()
メソッドをテストしたい動物のクラス、その名前と年齢を変更することではなく、その好きな食べ物を保つことによって、新たな動物のオブジェクトを作成する方法があるとします。
私はオリジナルと新しいオブジェクトが異なっていることを主張するAssert.assertNotEquals()
を使用したとします。
ここ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+(またはJUnitの5)両方の試験ランナーとアサーションツールとしての
@Test
void assertListNotEquals_JUnit_way() {
Animal scoubi = new Animal("scoubi", 10, "hay");
Animal littleScoubi = scoubi.createWithNewNameAndAge("little scoubi", 1);
Assert.assertNotEquals(scoubi, littleScoubi);
}
期待通りのテストは失敗しますが、開発者に提供される原因は本当に便利ではありません。それだけで値が異なることとすべきであると述べている出力実際toString()
パラメータで呼び出さAnimal
結果:
にjava.lang.AssertionError:値が異なっている必要があります。実際:動物
[NAME = scoubi、年齢= 10、favoriteFood =干し草
org.junit.Assert.fail(Assert.java:88)で
[OK]をオブジェクトはイコールではありません。しかし、ここで問題がある?
どのフィールドが正しく検査方法で評価されていませんか? 1 ?二 ?それらのすべて?
それが私たちのために期待されており、これが得している間の差分を作るならば、テストAPIがはるかに友好的であるだろうが、それはあなたがcreateWithNewNameAndAge()
実装で掘るする必要が発見する/デバッガを使用します。
のテストランナーとアサーションツールとしてテストのMatcherのAPIとしてのJUnit 4.11 の
ここでテストの同じシナリオそれはAnimal
状態のアサーションを行うことAssertJ(最高試験マッチャーAPI)を使用する:
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");
}
もちろん、テストはまだ失敗したが、今回はその理由を明確に記載されます:
にjava.lang.AssertionErrorます:
期待します:
<[ "scoubi"、10、 "干し草"]>
正確に(同じ順序で)含有する:
<[ "少しscoubi"、1、 "干し草"]>
が、いくつかの要素が見つかりませんでした。
<[ "少しscoubi"、1]>
などが期待されていなかった。
<[ "scoubi"、10]>
junit5.MyTest.assertListNotEquals_AssertJ(MyTest.java:26)で
私たちは返さ動物のAnimal::getName, Animal::getAge, Animal::getFavoriteFood
値のためにそれを読むことができ、我々はこれらの値を持つことを期待します:
"little scoubi", 1, "hay"
私たちは、これらの値を持っています:
"scoubi", 10, "hay"
だから我々はどこを調べる知っている:name
とage
が正しく評価されていません。
また、hay
のアサーションにAnimal::getFavoriteFood()
値を指定することも、より細かく返さAnimal
を主張することができます。私たちは、必ずしも必要ではないが、すべてのプロパティのオブジェクトは、いくつかの性質のために同じではないことがしたい。
だから、間違いなく、マッチャーAPIを使用すると、はるかに明確かつ柔軟です。
Modulo API の一貫性、JUnit が提供しなかった理由 assertNotEquals()
JUnit が次のようなメソッドを提供しなかったのと同じ理由です。
assertStringMatchesTheRegex(regex, str)
対assertStringDoesntMatchTheRegex(regex, str)
assertStringBeginsWith(prefix, str)
対assertStringDoesntBeginWith(prefix, str)
つまりアサーション ロジックで必要な種類のものに対して、特定のアサーション メソッドを提供することに終わりはありません。
次のような構成可能なテストプリミティブを提供する方がはるかに優れています。 equalTo(...)
, is(...)
, not(...)
, regex(...)
読みやすさと健全性を高めるために、代わりにプログラマがそれらをつなぎ合わせます。