【问题标题】:Why is assertThat(map1, sameInstance(map2)) not allowed?为什么 assertThat(map1, sameInstance(map2)) 不允许?
【发布时间】:2015-04-14 07:04:25
【问题描述】:

使用新的 Assert 语法,在测试身份时,可以这样写

Assert.assertThat(obj1, CoreMatchers.sameInstance(obj2))

而不是

Assert.assertSame(obj1, obj2)

我正在尝试断言地图的身份。所以我写了

Assert.assertThat(map1, CoreMatchers.sameInstance(map2))

其中 map 的类型为 HashMap<String,String> 但是我的测试在编译时失败了:

Error:(33, 9) error: no suitable method found for assertThat(Map,Matcher<Map<String,String>>)
method Assert.<T#1>assertThat(String,T#1,Matcher<? super T#1>) is not applicable
(cannot infer type-variable(s) T#1
(actual and formal argument lists differ in length))
method Assert.<T#2>assertThat(T#2,Matcher<? super T#2>) is not applicable
(cannot infer type-variable(s) T#2
(argument mismatch; Matcher<Map<String,String>> cannot be converted to Matcher<? super Map>))
where T#1,T#2 are type-variables:
T#1 extends Object declared in method <T#1>assertThat(String,T#1,Matcher<? super T#1>)
T#2 extends Object declared in method <T#2>assertThat(T#2,Matcher<? super T#2>)
Error:(33) error: no suitable method found for assertThat(Map,Matcher<Map<String,String>>)

为什么 JUnit(或 Hamcrest)不能确定使用哪个匹配器?

【问题讨论】:

  • map1 是原始的Map 还是Map&lt;String, String&gt;?如果它是原始的Map,它可能不应该是。
  • 运行时失败?这看起来像一个编译时错误。 map1map2 是如何声明的?
  • 糟糕!它在编译时失败。

标签: java unit-testing junit hamcrest


【解决方案1】:

事实证明,这与声明地图的身份无关 - 代码是正确的 - 但它确实与泛型有关。

我试图测试的类看起来像这样:

public class Response<T>{
    public final Map<String, String> map;
    public final T data;
}

但是,测试是这样写的:

@Test
public void testStuff() throws Exception {
    Map<String, String> map = new HashMap<>();
    Object data = new Object();
    Response target = new Response<>(map, data);
    assertThat(target.map, sameInstance(map));
    assertThat(target.data, sameInstance(data));
}

编译错误实际上在最后一行,因为 T 对编译器来说是未知的(&lt;?&gt;),所以它找不到合适的匹配器。我通过声明原始类型来修复测试。

@Test
public void testStuff() throws Exception {
    Map<String, String> map = new HashMap<>();
    Object data = new Object();
    Response<Object> target = new Response<>(map, data);
    assertThat(target.map, sameInstance(map));
    assertThat(target.data, sameInstance(data));
}

但我觉得奇怪的是为什么编译器会抱怨上一行...

【讨论】:

  • 如果你使用原始Response,它的实例变量也是原始类型,即使Response的类型参数不涉及。 target.map 是原始的,如果 target 是。
  • 令人着迷!感谢您的见解!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-19
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
  • 2017-10-27
  • 2016-01-25
  • 2012-04-22
相关资源
最近更新 更多