2011-02-13 40 views
20

我想斷言List<Achievement>包含TestAchievement類型的成員。Java Hamcrest:Collection包含的項目類型

這裏是我的說法:

List<Achievement> achievements; // Populated elsewhere 
assertThat(achievements,hasItem(isA(TestAchievement.class))); 

這並不編譯,報告錯誤:

The method assertThat(T, Matcher) in the type Assert is not applicable for the arguments (List, Matcher<Iterable<TestAchievement>>)

什麼是使用Hamcrest這種說法的正確語法?

回答

21

感謝所有幫助。

這裏的帖子顯示這是Hamcrest的缺陷,所以我前往hacmrest站點註冊一個bug,我發現我使用的mvn/ivy依賴聲明已經過時,給了我Hamcrest的舊版本。

此錯誤1.1存在,這是最新的,如果使用聲明

<dependency org="org.hamcrest" name="hamcrest-all" rev="1.1"> 

但是,正確的depedency聲明:

<dependency org="org.hamcrest" name="hamcrest-library" rev="1.3.RC2"/> 

更新到這個問題得到了解決。在我的測試中使用的語法是:

assertThat(achievements, hasItem(isA(TestAchievement.class))); 
2

我一直在與此爭論一段時間,似乎我知道的唯一方法是將List<Achievement>轉換爲List<Object>。問題是CoreMatchers.instanceOf()返回Matcher<Object>

隨着這一修改,我能夠得到這個工作: -

List<Object> achievements = new ArrayList<Object>(); 
achievements.add(new Achievement()); 
achievements.add(new TestAchievement()); 
assertThat(achievements, hasItem(instanceOf(TestAchievement.class))); 
2

http://code.google.com/p/hamcrest/source/browse/trunk/hamcrest-java/hamcrest-core/src/main/java/org/hamcrest/MatcherAssert.java簽名

assertThat(T actual, Matcher<? super T> matcher) 

所以問題是,你的匹配是Matcher<TestAchievement>,不一個匹配器,適用於任何超類或成就接口的實例。

它看起來像instanceOf匹配器只是有一個越野車類型綁定。 您可以解決這個bug做類似

@SuppressWarnings("unchecked") 
Matcher/*no_param*/ isATestAchievement = instanceOf(TestAchievement.class); 
assertThat(..., isATestAchievement); 
+0

這是一個很好的例子。適用於我,但只適用於Hamcrest 1.1。升級到1.2或1.3.0RC0會給我n錯誤。 – 2011-03-17 10:55:38

+0

的錯誤(1.2)堆棧跟蹤: java.lang.NoSuchMethodError:org.hamcrest.Matcher.describeMismatch(Ljava /郎/對象; Lorg/hamcrest /描述;)V \t在org.hamcrest.core.IsCollectionContaining。 matchesSafely(IsCollectionContaining.java:31) \t在org.hamcrest.core.IsCollectionContaining.matchesSafely(IsCollectionContaining.java:14) \t在org.hamcrest.TypeSafeDiagnosingMatcher.matches(TypeSafeDiagnosingMatcher.java:54) \t在org.hamcrest .MatcherAssert.assertThat(MatcherAssert.java:12) \t at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8) – 2011-03-17 10:56:41

+0

@JesperRønn-Jensen請參閱[本答案] (http://stackoverflow.com/questions/4981586/java-hamcrest-collection-contains-item-of-type/20751480#20751480)。這與hamcrest 1.1和1.3一起工作。 – 2013-12-23 21:46:37

3
assertThat(achievements, hasItem(
    IsInstanceOf.<Achievement>instanceOf(TestAchievement.class))); 
+0

該行不能編譯。以下是錯誤消息:類型IsInstanceOf的方法instanceOf(類)不是通用的;它不能用參數參數化` – limc 2011-02-13 03:01:22

+0

@limc它在主幹代碼中是通用的:http://code.google.com/p/hamcrest/source/browse/trunk/hamcrest-java/hamcrest-core/src/ main/java/org/hamcrest/core/IsInstanceOf.java – NamshubWriter 2011-02-13 15:12:43

3

我一直在爭取這一段時間,沒有任何一種方法真的有預期的結果。出於純粹的絕望,我試圖轉換爲陣列,看看是否有所作爲:

List<Object> listOfThings = (List) someService.findThings(); // your business logic here 
Object[] arrayOfThings = listOfThings.toArray(new Object[listOfThings.size()]); 

assertThat(arrayOfThings, hasItemInArray(instanceOf(SpecialThing.class))); 

它確實有所作爲。現在我的測試完美無瑕。複製到數組的一行似乎是一個合理的權衡,以節省很多麻煩。

2

Actuall它不適用於一個更復雜的匹配器,即使使用最新版本。

assertThat(result.getAnswers(), 
      Matchers.hasItem(Matchers.hasProperty("content"))); 

它不會工作,你會得到一個:

The method assertThat(T, Matcher) in the type Assert is not applicable for the arguments (Set, Matcher>)

您可以將其轉換爲一個數組解決這個問題:

assertThat(result.getAnswers().toArray(), hasItemInArray(Matchers.hasProperty("content", equalTo("<h4>new comment</h4>")))); 
8

有Java 6中一個bug那與此有關。

該代碼將引發各種錯誤,如「無法找到符號......」

assertThat(achievements, hasItem(isA(TestAchievement.class))); 

工作圍繞這是聲明匹配作爲一個變量,然後引用該變量。重要的是要注意,變量的類型,特別是泛型部分,對於此工作非常重要。

Matcher<Iterable<? super TestAchievement>> matcher = hasItem(isA(TestAchievement.class)); 
assertThat(achievements, matcher); 

有趣的是,如果你使用的instanceOf()代替isA()你再次遇到問題。 (儘管如果你忽略了這個警告,這可能對你仍然有用)。擴展你可以使用的以前的修復:

Matcher<TestAchievement> itemMatcher = Matchers.instanceOf(TestAchievement.class); 
Matcher<Iterable<? super TestAchievement>> matcher = hasItem(itemMatcher); 
assertThat(achievements, matcher);