【问题标题】:Conflicting overloads for Hamcrest matcherHamcrest 匹配器的冲突重载
【发布时间】:2013-09-04 13:02:23
【问题描述】:

匹配器IsIterableContainingInAnyOrder 对静态工厂方法containsInAnyOrder 有两个重载(都具有返回类型Matcher<java.lang.Iterable<? extends T>>):

  1. containsInAnyOrder(java.util.Collection<Matcher<? super T>> itemMatchers)
  2. containsInAnyOrder(Matcher<? super T>... itemMatchers)

现在考虑以下程序:

import static org.hamcrest.collection.IsIterableContainingInAnyOrder.containsInAnyOrder;
import static org.hamcrest.core.IsEqual.equalTo;
import static org.junit.Assert.assertThat;

import java.util.Arrays;

import org.junit.Test;

public class SomeTest {

    @SuppressWarnings("unchecked")
    @Test
    public void foo() {
        assertThat(Arrays.asList("foo","bar"), 
                       containsInAnyOrder(equalTo("foo"), equalTo("bar")));
    }

}

当它作为 JUnit 测试执行时,它按预期通过了。它使用上面显示的containsInAnyOrder 的第二个重载。

现在,当我将断言更改为此(与documentation of the first overload 中给出的示例完全匹配)时:

assertThat(Arrays.asList("foo","bar"), 
           containsInAnyOrder(Arrays.asList(equalTo("foo"), equalTo("bar"))));
                              ^^^^^^^^^^^^^^

它不再编译了,因为现在编译器推断containsInAnyOrder的返回类型是

Matcher<Iterable<? extends List<Matcher<String>>>>

编译器似乎仍然选择第二个重载。如果它使用第一个,该示例应该可以工作。为什么它会这样?我怎样才能做到这一点?

我正在使用 Hamcrest 1.3 和 Oracle Java 1.7。

【问题讨论】:

    标签: java overloading hamcrest


    【解决方案1】:

    它实际上匹配两个重载方法。我不确定为什么会选择第一个,但您可以提供提示以使其选择正确的方法。

    通过将参数转换为Collection

    assertThat(Arrays.asList("foo","bar"),
            containsInAnyOrder((Collection)Arrays.asList(equalTo("foo"), equalTo("bar"))));
    

    或通过将泛型类型 T 指定为 &lt;String&gt;(但不适用于静态导入):

    assertThat(Arrays.asList("foo","bar"),
            IsIterableContainingInAnyOrder.<String>containsInAnyOrder(Arrays.asList(equalTo("foo"), equalTo("bar"))));
    

    【讨论】:

    • 为了类型安全,我推荐第二个版本。此外,您可以写 Matchers.&lt;String&gt;containsInAnyOrder 而不是 IsIterableContainingInAnyOrder.&lt;String&gt;containsInAnyOrder
    【解决方案2】:

    当您匹配自己的对象而不是简单的字符串时,这甚至更难使泛型发挥作用。如果您在问题的第一个示例中使用 varargs containsInAnyOrder(Matcher&lt;? super T&gt;... itemMatchers),您将收到 Unchecked generics array creation for varargs parameter 警告。例如:

    assertThat(myDTOList, 
        containsInAnyOrder(sameStateAs(expectedMyDTO1), sameStateAs(expectedMyDTO2));
    

    然后解决问题中 OP 所述问题的一种方法是按如下方式定义您的匹配器集合:

    Collection<Matcher<? super MyDTO>> expectedMyDTOs = 
        Arrays.<Matcher<? super MyDTO>>asList(sameStateAs(expectedMyDTO1), sameStateAs(expectedMyDTO2));
    
    // Use like this:
    assertThat(myDTOList, 
        containsInAnyOrder(expectedMyDTOs);
    

    【讨论】:

    • 哇,? super MyDTO 成功了。 ? super Object 没有 :) 非常感谢!
    【解决方案3】:

    使用 hamcrest 1.3,您可以直接使用 Matchers 类而不是 @eee 提到的 IsIterableContainingInAnyOrder。 Matchers 实际上只是为您调用 IsIterableContainingInAnyOrder。

    import static org.hamcrest.core.IsEqual.equalTo;
    import static org.junit.Assert.assertThat;
    
    import org.hamcrest.Matchers;
    import java.util.Arrays;
    import org.junit.Test;
    
    public class SomeTest
    {
        @Test
        public void foo() {
            assertThat(Arrays.asList("foo","bar"), 
                Matchers.<OrderValidationStep>containsInAnyOrder("foo", "bar"));
        }
    }
    

    请注意,如果您想 Type 调用 containsInAnyOrder,则不能使用静态导入,这样就无需添加 @SuppressWarnings("unchecked")

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-07
      • 1970-01-01
      • 1970-01-01
      • 2015-09-15
      • 1970-01-01
      • 2023-04-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多