84

環境

クラスの簡単なJUnitテストを作成しています。MyObject

は、 StringMyObject可変引数を取る静的ファクトリ メソッドから作成できます。

MyObject.ofComponents("Uno", "Dos", "Tres");

が存在する間はいつでも、クライアントはメソッドを介してList<E>MyObjectの形式で作成されたパラメータを調べることができます。.getComponents()

myObject.ofComponents(); // -> List<String>: { "Uno", "Dos", "Tres" }

つまり、 aMyObjectは、それを作成したパラメーターのリストを記憶し、公開します。この契約の詳細:

  • の順序はgetComponents、オブジェクトの作成で選択した順序と同じになります
  • 後続の文字列コンポーネントの重複は許可され、順番に保持されます
  • の動作nullは未定義です (他のコードはnull、ファクトリへの取得がないことを保証します)
  • オブジェクトのインスタンス化後にコンポーネントのリストを変更する方法はありません

StringMyObjectのリストからを作成し、を介して同じリストを返すことができることを確認する簡単なテストを作成しています。私はすぐにこれを行いますが、これは現実的なコード パスの距離で発生するはずです。.getComponents()

コード

ここで私の試み:


List<String> argumentComponents = Lists.newArrayList("One", "Two", "Three");
List<String> returnedComponents =
    MyObject.ofComponents(
        argumentComponents.toArray(new String[argumentComponents.size()]))
        .getComponents();
assertTrue(Iterables.elementsEqual(argumentComponents, returnedComponents));

質問

  • これら 2 つのリストを比較するには、ビルド パスにライブラリがある場合、Google Guava が最善の方法ですか? これは私がずっと悩んできたことです。Iterable<E>を超えるこのヘルパー メソッドを使用する必要がありますか? 単体テストのリストを比較する標準的な方法は何ですか?Iterables.elementsEqual().equals()

取得したいオプションの洞察

  • メソッドテストは合理的に設計されていますか? 私はJUnitの専門家ではありません。
  • List<E>.toArray()を E の可変引数に変換する最良の方法はありますか?
4

8 に答える 8

83

単に使用しないのはなぜList#equalsですか?

assertEquals(argumentComponents, imapPathComponents);

の契約List#equals:

2 つのリストは、同じ要素が同じ順序で含まれている場合に等しいと定義されます。

于 2012-09-19T13:17:12.757 に答える
58

失敗した場合にはるかに優れた出力が得られるため、Hamcrest を使用することを好みます。

Assert.assertThat(listUnderTest, 
       IsIterableContainingInOrder.contains(expectedList.toArray()));

報告する代わりに

expected true, got false

それは報告します

expected List containing "1, 2, 3, ..." got list containing "4, 6, 2, ..."

IsIterableContainingInOrder.contain

ハムクレスト

Javadocによると:

検査された Iterable を 1 回パスすると一連のアイテムが生成され、それぞれが指定されたアイテムの対応するアイテムと論理的に等しい場合に一致する Iterables のマッチャーを作成します。正の一致の場合、検査された iterable は、指定されたアイテムの数と同じ長さでなければなりません

したがって、listUnderTestには同じ数の要素が必要であり、各要素は期待値と順番に一致する必要があります。

于 2012-09-19T13:23:53.507 に答える
11

List 実装の equals() メソッドは、要素ごとの比較を行う必要があるため、

assertEquals(argumentComponents, returnedComponents);

はるかに簡単です。

于 2012-09-19T13:17:04.810 に答える
10

org.junit.Assert.assertEquals()そしてorg.junit.Assert.assertArrayEquals()仕事をする。

次の質問を回避するには: 順序を無視する場合は、すべての要素を設定してから比較します:Assert.assertEquals(new HashSet<String>(one), new HashSet<String>(two))

ただし、重複を無視したいだけで、リストしたオーダー ラップを保持したい場合は、LinkedHashSet.

さらに別のヒント。比較が失敗するまで、このトリックAssert.assertEquals(new HashSet<String>(one), new HashSet<String>(two))はうまく機能します。この場合、(少なくとも複雑なオブジェクトの場合) セット内の順序がほとんど予測できないため、混乱を招く可能性のあるセットの文字列表現に関するエラー メッセージが表示されます。したがって、私が見つけたトリックは、コレクションを の代わりにソートされたセットでラップすることですHashSetTreeSetカスタムコンパレータで 使用できます。

于 2012-09-19T13:19:36.990 に答える
5

優れたコード可読性のために、Fest Assertionsはアサーションリストを適切にサポートしています。

したがって、この場合は次のようになります。

Assertions.assertThat(returnedComponents).containsExactly("One", "Two", "Three");

または、予想されるリストを配列にしますが、より明確であるため、上記のアプローチを好みます。

Assertions.assertThat(returnedComponents).containsExactly(argumentComponents.toArray());
于 2012-09-20T08:30:51.373 に答える
1
  • Iterables.elementsEqual最良の選択であるかどうかについての私の答え:

Iterables.elementsEqual2 秒を比較するには十分Listです。

Iterables.elementsEqualはより一般的なシナリオで使用され、より一般的なタイプを受け入れます: Iterable. つまり、 aListと a を比較することさえできますSet。(繰り返し順で、重要です)

確かにequalsArrayListを定義するのはかなり良いです.equalsを直接呼び出すことができます. LinkedList明確に定義されていないリストを使用する場合Iterables.elementsEqualは、が最良の選択です。1 つのことに注意する必要があります:Iterables.elementsEqual受け入れませんnull

  • リストを配列に変換するには:Iterables.toArrayの方が簡単です。

  • 単体テストでは、空のリストをテスト ケースに追加することをお勧めします。

于 2012-09-19T14:00:35.253 に答える