为什么要使用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 )

如果结构变得更复杂,但是你看到更多的优势,那么也许是好消息? 可读性?

对于存在与您的意图完全匹配的assertFoo情况,没有什么大的优势。 在这些情况下,他们的performance几乎一样。

但是,当你来检查是更复杂的,那么这个优势就变得更加明显了:

 assertTrue(foo.contains("someValue") && foo.contains("anotherValue")); 

 assertThat(foo, hasItems("someValue", "anotherValue")); 

我们可以讨论哪一个更容易阅读,但是一旦断言失败,你会从断言中得到一个很好的错误信息,但是assertThat只有极less量的信息。

断言这将告诉你什么是断言,你取而代之。 assertTrue只会告诉你,你false ,如果你期望true

JUnit 4.4版本的发布说明 (介绍它)介绍了四个优点:

  • 更可读性和可键入性:这个语法允许你根据主语,动词,宾语(assert“x是3”)而不是assertEquals ,它使用动词,宾语,主语(assert“等于3 x”)
  • 组合:任何匹配器语句都可以被否定( not(s) ),合并( or(s).or(t) ),映射到集合( each(s) ),或在自定义组合中使用( afterFiveSeconds(s)
  • 可读的故障消息。 (……)
  • 自定义匹配器。 通过自己实现Matcher接口,您可以获得您自己的自定义断言的所有上述优点。

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

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

除了hamcrest,你也可以使用fest断言 。 它们比Hamcrest一些优点,例如:

  • 他们更可读
    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日更新

节日不再活跃,而是使用AssertJ

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

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

 assertEqual(1, foo); 

– 要么 –

 assertThat(foo, is(1)); 

采用第一种方法,很容易忘记正确的顺序,并将其向后键入。 然后,而不是说testing失败,因为它预期1和2,消息是倒退。 testing通过时不是问题,但当testing失败时可能导致混淆。

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

例:

 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. 你可以使你的testing更具体
  2. 如果testing失败,则会得到更详细的exception
  3. 更容易阅读testing

btw:你也可以在assertXXX中写文本…

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

接近自然语言。

更容易阅读,更容易分析代码。 Programer花费更多时间分析代码,而不是编写新代码。 所以如果代码易于分析,那么开发人员应该更高效。

PS代码应该是写得很好的书。 自我logging的代码。

有断言的优点assertEquals –
1)更可读
2)关于失败的更多信息
3)编译时间错误 – 而不是运行时错误
4)写作testing条件的灵活性
5)便携 – 如果你使用的是Hamcrest,你可以使用jUnit或者TestNG作为底层框架。