在hamcrest中,Matchers.hasItem和friends返回一个Matcher<Iterable<? super T>>,但是contains和friends返回一个Matcher<Iterable<? extends T>>。为什么有区别?
Matchers.hasItem
Matcher<Iterable<? super T>>
contains
Matcher<Iterable<? extends T>>
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);
还要注意,Matcher接口在其成员方法中不使用其泛型参数(特别是在接受Object的匹配中)-泛型参数仅在组合Matchers时才起作用。
Matcher
1条答案
按热度按时间gtlvzcf81#
我的理解是根本原因是Naming of method Matchers#contains is ambiguous #140
在这里的代码审查中,人们经常误解这一点:
意思是:“Assert集合包含'x'”。
但它实际上的意思是这样的:“Assert集合只包含'x'”。
这导致在我们的代码审查中提出了许多不必要的问题,其中代码被更新为使用Hamcrest,仅仅因为它的阅读与实际操作不同。
与此同时,希望用Hamcrest编写新代码的人正在使用自动完成来寻找合适的方法,并且在发现他们真正需要hasItem之前经常尝试使用contains。
我建议将containsOnly作为一个新名称,但containsInAnyOrder也有同样的问题,我发现很难在其中添加额外的单词。
因此给出:
还要注意,
Matcher
接口在其成员方法中不使用其泛型参数(特别是在接受Object的匹配中)-泛型参数仅在组合Matchers时才起作用。