使用 Hamcrest everyItem() 的编译错误

Compilation error using Hamcrest everyItem()

我正在尝试在 Hamcrest 的 everyItem() 上使用 hasKey(),但出现以下编译错误:

error: no suitable method found for assertThat(List<Map<String,Object>>,Matcher<Iterable<Map<? extends String,?>>>)
        assertThat(data, everyItem(hasKey("index")));
        ^
    method Assert.<T#1>assertThat(T#1,Matcher<? super T#1>) is not applicable
      (actual argument Matcher<Iterable<Map<? extends String,?>>> cannot be converted to Matcher<? super List<Map<String,Object>>> by method invocation conversion)
    method Assert.<T#2>assertThat(String,T#2,Matcher<? super T#2>) is not applicable
      (cannot instantiate from arguments because actual and formal argument lists differ in length)
  where T#1,T#2 are type-variables:
    T#1 extends Object declared in method <T#1>assertThat(T#1,Matcher<? super T#1>)
    T#2 extends Object declared in method <T#2>assertThat(String,T#2,Matcher<? super T#2>)
Note: Some input files use unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error

这是重现错误的简单 JUnit 测试:

package test;

import org.junit.Test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static org.hamcrest.collection.IsMapContaining.hasKey;
import static org.hamcrest.core.Every.everyItem;
import static org.junit.Assert.assertThat;

public class Test {

    @Test
    public void test(){
        List<Map<String, Object>> data = new ArrayList<>();
        Map<String,Object> element = new HashMap<>();
        element.put("index", 1);
        data.add(element);

        assertThat(data, everyItem(hasKey("index")));
    }



}

有谁知道如何解决这个编译错误?

这是嵌套泛型的情况。

data 当前被声明为 List<Map<String, Object>>,而 everyItem(hasKey("index")) 被推断为 returning a Matcher<Iterable<Map<? extends String, ?>>>.

如编译错误消息所述

The method assertThat(T, Matcher<? super T>) in the type Assert is not applicable for the arguments (List<Map<String,Object>>, Matcher<Iterable<Map<? extends String,?>>>)

这归结为 hasKey 具有 return 类型的 Map<? extends T, ? 而不是 Map<T, ?>,但这可能是有充分理由的。

幸运的是,您的代码足够简单,您可以将 data 声明为

List<Map<? extends String, ?>> data = new ArrayList<>();

并编译代码。