有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

hamcrest我怎样才能得到contains(List<Matcher>itemmachers)来用Java 7编译?

我正在学习Hamcrest 1.3,我想为Matchers中的每个Hamcrest静态方法提供一个示例。Javadoc已经有了一些方法的示例,这很有帮助。我用Java 8测试了以下contains代码片段,结果通过了测试:

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

然而,我的团队目前正在使用Java 7,所以我希望确保所有示例都能在该版本中工作。上述代码片段在Java 7中产生以下错误:

no suitable method found for assertThat(java.util.List,org.hamcrest.Matcher>>>) method org.junit.Assert.assertThat(T,org.hamcrest.Matcher) is not applicable (actual argument org.hamcrest.Matcher>>> cannot be converted to org.hamcrest.Matcher> by method invocation conversion) method org.junit.Assert.assertThat(java.lang.String,T,org.hamcrest.Matcher) is not applicable (cannot instantiate from arguments because actual and formal argument lists differ in length)

我知道Java8为静态方法添加了新的隐式类型特性,我认为这可能与此有关。我试图重构参数并将其转换为预期参数,但这会导致相同的错误:

List<String> actual = Arrays.asList("foo", "bar");
List<Matcher<String>> expected = Arrays.asList(equalTo("foo"), 
                                               equalTo("bar"));
assertThat(actual, contains(expected));

在Java7中调用static <E> Matcher<java.lang.Iterable<? extends E>> contains(java.util.List<Matcher<? super E>> itemMatchers)的正确方法是什么


共 (2) 个答案

  1. # 1 楼答案

    在Hamcrest Javadoc中,针对contains()的方法签名是:

     public static <E> Matcher<Iterable<? extends E>> contains(List<Matcher<? super E>> itemMatchers);
    

    在上面的签名中需要注意的重要一点是List<Matcher<? super E>>。Java 7无法从List<Matcher<String>>推断List<Matcher<? super E>>。另外contains()被重载,因此Java 7所针对的方法的签名是:

    public static <E> Matcher<Iterable<? extends E>> contains(E... items);
    

    这就是为什么你会收到神秘的编译错误信息

    幸运的是,解决方法非常简单:

    List<String> actual = Arrays.asList("foo", "bar");
    List<Matcher<? super String>> expected = Arrays.<Matcher<? super String>>asList(equalTo("foo"), 
                                                                                    equalTo("bar"));
    assertThat(actual, contains(expected));
    
  2. # 2 楼答案

    我没有安装库来测试这一点,但我认为这是一个子类型问题

    • expected具有类型List<Matcher<String>>
    • contains(expected)有类型Matcher<Iterable<String>>
    • actual有类型List<String>
    • assertThat需要类型为T的第一个参数和类型为Matcher<T>的第二个参数
    • 你的TList<String>,这意味着它需要类型为Matcher<List<String>>的第二个参数,而不是Matcher<Iterable<String>>

    我猜这应该可以解决这个问题:

    Iterable<String> actual = Arrays.asList("foo", "bar");
    List<Matcher<String>> expected = Arrays.asList(equalTo("foo"), 
                                                   equalTo("bar"));
    assertThat(actual, contains(expected));
    

    再说一次,我还没有测试这个补丁,但它似乎可以解决类型问题