web-dev-qa-db-ja.com

特定のプロパティを持つ要素を含むIterableをアサートするにはどうすればよいですか?

このシグネチャを使用してメソッドを単体テストしたいとします:

List<MyItem> getMyItems();

MyItemは多くのプロパティを持つPojoであり、そのうちの1つは"name"であり、getName()を介してアクセスすると仮定します。

検証に関心があるのは、List<MyItem>、またはIterableに2つのMyItemインスタンスが含まれ、その"name"プロパティの値が"foo"および"bar"。他のプロパティが一致しない場合、このテストの目的はあまり気にしません。名前が一致すれば、テストは成功です。

可能であればワンライナーにしたいと思います。ここに、私がやりたいと思う種類の「疑似構文」があります。

assert(listEntriesMatchInAnyOrder(myClass.getMyItems(), property("name"), new String[]{"foo", "bar"});

ハムクレストは、この種のことには適していますか?もしそうなら、上記の私の疑似構文の正確なバージョンは何でしょうか?

93
Kevin Pauli

私を正しい方向に向けてくれた@Razvanに感謝します。私はそれを1行で取得することができ、Hamcrest 1.3のインポートを成功裏に追い詰めました。

インポート:

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.Matchers.contains;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;

コード:

assertThat( myClass.getMyItems(), contains(
    hasProperty("name", is("foo")), 
    hasProperty("name", is("bar"))
));
111
Kevin Pauli

試してください:

assertThat(myClass.getMyItems(),
                          hasItem(hasProperty("YourProperty", is("YourValue"))));
47
Razvan

特にハムクレストではありませんが、ここで言及する価値があると思います。 Java8でよく使用するのは次のようなものです。

assertTrue(myClass.getMyItems().stream().anyMatch(item -> "foo".equals(item.getName())));

(ロドリゴ・マニャリのわずかな改善に編集。少し冗長です。コメントを参照してください。)

読むのが少し難しいかもしれませんが、タイプとリファクタリングの安全性が好きです。複数のBeanプロパティを組み合わせてテストするのにも便利です。例えばフィルタlambdaにJavaのような&&式を使用します。

38
Mario Eis

Assertj はこれが得意です。

import static org.assertj.core.api.Assertions.assertThat;

    assertThat(myClass.getMyItems()).extracting("name").contains("foo", "bar");

Hamcrestと比較したassertjの大きな利点は、コード補完を簡単に使用できることです。

19
Frank Neblung

AssertJはextracting()で優れた機能を提供します:Functionsを渡してフィールドを抽出できます。コンパイル時にチェックを提供します。
最初に簡単にサイズをアサートすることもできます。

それは与えるだろう:

import static org.assertj.core.api.Assertions;

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName)
          .containsExactlyInAnyOrder("foo", "bar"); 

containsExactlyInAnyOrder()は、順序に関係なく、リストにはこれらの値のみが含まれていることを表明します。

順序に関係なくリストにこれらの値が含まれているが、他の値が含まれている可能性があることをアサートするには、contains()を使用します。

.contains("foo", "bar"); 

サイドノートとして:Listの要素から複数のフィールドをアサートするには、AssertJで各要素の期待値をTuple()関数にラップすることでそれを行います。

import static org.assertj.core.api.Assertions;
import static org.assertj.core.groups.Tuple;

Assertions.assertThat(myClass.getMyItems())
          .hasSize(2)
          .extracting(MyItem::getName, MyItem::getOtherValue)
          .containsExactlyInAnyOrder(
               Tuple("foo", "OtherValueFoo"),
               Tuple("bar", "OtherValueBar")
           ); 
9
davidxxx

Listが具象クラスである限り、MyItemにequals()メソッドを実装している限り、単にcontains()メソッドを呼び出すことができます。

// given 
// some input ... you to complete

// when
List<MyItems> results = service.getMyItems();

// then
assertTrue(results.contains(new MyItem("foo")));
assertTrue(results.contains(new MyItem("bar")));

アサートする値を受け入れるコンストラクターを実装したと仮定します。これは一行ではありませんが、両方を一度にチェックするよりも、どの値が欠落しているかを知ることは有用です。

5
Brad