junit 为什么Matchers.hasItem返回Matcher〈Iterable〈?super T>>,而Matchers.contains返回Matcher〈Iterable〈?extends T>>?

oxcyiej7  于 2023-04-12  发布在  其他
关注(0)|答案(1)|浏览(141)

在hamcrest中,Matchers.hasItem和friends返回一个Matcher<Iterable<? super T>>,但是contains和friends返回一个Matcher<Iterable<? extends T>>。为什么有区别?

gtlvzcf8

gtlvzcf81#

我的理解是根本原因是Naming of method Matchers#contains is ambiguous #140
在这里的代码审查中,人们经常误解这一点:

assertThat(collection, contains("x"));

意思是:“Assert集合包含'x'”。
但它实际上的意思是这样的:“Assert集合只包含'x'”。
这导致在我们的代码审查中提出了许多不必要的问题,其中代码被更新为使用Hamcrest,仅仅因为它的阅读与实际操作不同。
与此同时,希望用Hamcrest编写新代码的人正在使用自动完成来寻找合适的方法,并且在发现他们真正需要hasItem之前经常尝试使用contains。
我建议将containsOnly作为一个新名称,但containsInAnyOrder也有同样的问题,我发现很难在其中添加额外的单词。
因此给出:

class BaseFoo {}
class Foo1 extends BaseFoo {}
class Foo2 extends BaseFoo {}

Foo1 foo1 = new Foo1();
Foo2 foo2 = new Foo2();

Matcher<Iterable<? extends BaseFoo>> containsMatcher = Matchers.contains(foo1, foo2);
Matcher<Iterable<? super Foo1>> hasItemsMatcher = Matchers.hasItem(foo1);
  • containsMatcher永远不会匹配包含BaseFoo超类的Iterable
  • hasItemsMatcher可以匹配包含BaseFoo超类的Iterable

还要注意,Matcher接口在其成员方法中不使用其泛型参数(特别是在接受Object的匹配中)-泛型参数仅在组合Matchers时才起作用。

相关问题