为什么要使用 Hamcrest-Matcher 和 assertThat ()而不是传统的 assertXXX ()-方法

当我查看 Assert 类 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 )有什么大的优势。

如果结构变得更加复杂,对于消息来说可能是件好事,但是你是否看到了更多的优势? 可读性?

60328 次浏览

对于那些存在与您的意图完全匹配的 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"]

我们可以讨论哪一个更容易读取,但是一旦断言失败,您将从 assertThat得到一个很好的错误消息,但是从 assertTrue得到的信息量非常少。

版本4.4的 JUnit 释放通知书(引入它的地方)有四个优点:

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

创建新语法 给你的人提供了更详细的论证。

例如:

assertThat(5 , allOf(greaterThan(1),lessThan(3)));
//  java.lang.AssertionError:
//  Expected: (a value greater than <1> and a value less than <3>)
//       got: <5>
assertTrue("Number not between 1 and 3!", 1 < 5 && 5 < 3);
//  java.lang.AssertionError: Number not between 1 and 3!
  1. 你可以让你的测试更加具体
  2. 如果测试失败,就会得到一个更详细的异常
  3. 更容易阅读测试

顺便说一下: 你也可以用 assertXXX 写文本..。

一个非常基本的理由是,很难搞乱新的语法。

假设一个特定的值 foo 在测试之后应该是1。

assertEqual(1, foo);

或者

assertThat(foo, is(1));

对于第一种方法,很容易忘记正确的顺序,然后向后键入。然后不是说测试失败是因为它期望1得到2,而是消息向后。当测试通过时不是问题,但是当测试失败时会导致混乱。

在第二个版本中,几乎不可能犯这种错误。

基本上是为了 增加代码的可读性

除了吊床,你也可以使用 节日主张。 他们有 与吊床相比有一些优势,例如:

  • 它们更易读
    (assertEquals(123, actual); // reads "assert equals 123 is actual" vs
    assertThat(actual).isEqualTo(123); // reads "assert that actual is equal to 123")
  • 它们是可发现的(您可以使用任何 IDE 进行自动完成)。

举几个例子

import static org.fest.assertions.api.Assertions.*;


// common assertions
assertThat(yoda).isInstanceOf(Jedi.class);
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron);
assertThat(frodo).isIn(fellowshipOfTheRing);
assertThat(sauron).isNotIn(fellowshipOfTheRing);


// String specific assertions
assertThat(frodo.getName()).startsWith("Fro").endsWith("do")
.isEqualToIgnoringCase("frodo");


// collection specific assertions
assertThat(fellowshipOfTheRing).hasSize(9)
.contains(frodo, sam)
.excludes(sauron);




// map specific assertions (One ring and elves ring bearers initialized before)
assertThat(ringBearers).hasSize(4)
.includes(entry(Ring.oneRing, frodo), entry(Ring.nenya, galadriel))
.excludes(entry(Ring.oneRing, aragorn));

2016年10月17日更新

Fest 不再活动,改为使用 < strong > AssertJ

assertThat(frodo.getName()).isEqualTo("Frodo");

接近自然语言。

更容易阅读,更容易分析代码。 程序员花费更多的时间来分析代码,而不是编写新的代码。因此,如果代码容易分析,那么开发人员应该更有效率。

附言。 代码应该是一本写得很好的书。 自我文档化的代码。

AssertThat 比 assertEquals 更有优势
1)更易读
2)更多关于故障的资料
3)编译时错误-而不是运行时错误
4)写作测试条件的灵活性
5)可移植性-如果你使用的是 hamcrest-你可以使用 jUnit 或 TestNG 作为底层框架。