为什么我应该使用Hamcrest-Matcher和assertThat()而不是传统的assertXXX()-Methods。

2022-08-31 07:07:34

当我查看断言类 JavaDoc 中的示例时

assertThat("Help! Integers don't work", 0, is(1)); // fails:
// failure message:
// Help! Integers don't work
// expected: is <1> 
// got value: <0>
assertThat("Zero is one", 0, is(not(1))) // passes

比方说,我没有看到一个很大的优势。assertEquals( 0, 1 )

如果构造变得更加复杂,也许对于消息来说很好,但是你看到更多的优势了吗?可读性?


答案 1

对于那些存在与您的意图完全匹配的情况,没有太大的优势。在这些情况下,它们的行为几乎相同。assertFoo

但是,当您进行稍微复杂的检查时,其优势就会变得更加明显:

val foo = List.of("someValue");
assertTrue(foo.contains("someValue") && foo.contains("anotherValue"));
Expected: is <true>
         but: was <false>

断续器

val foo = List.of("someValue");
assertThat(foo, containsInAnyOrder("someValue", "anotherValue"));
Expected: iterable with items ["someValue", "anotherValue"] in any order
     but: no item matches: "anotherValue" in ["someValue"]

人们可以讨论其中哪一个更易于阅读,但是一旦断言失败,您将从 中获得一条很好的错误消息,但只有非常少量的信息来自。assertThatassertTrue


答案 2

版本 4.4(引入它的 JUnit)的发行说明说明了四个优点:

  • 更具可读性和可类型化:这种语法允许您根据主语,动词,宾语(断言“x是3”)而不是断言等式来思考,后者使用动词,宾语,主语(断言“等于3 x”)
  • 组合:任何匹配器语句都可以被否定(not(s))、组合(any(s)或(t))、映射到集合(每个集合)或用于自定义组合(afterFiveSeconds(s)))
  • 可读的失败消息。(...)
  • 自定义匹配器。通过自己实现 Matcher 接口,您可以获得自己的自定义断言的所有上述好处。

来自创建新语法的人的更详细的论证:这里