Почему я должен использовать 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 ).

Это хорошо, может быть, для сообщений, если конструкции становятся более сложными, но вы видите больше преимуществ? Читаемость?

Ответ 1

Нет большого преимущества для тех случаев, когда существует assertFoo, который точно соответствует вашему намерению. В этих случаях они ведут себя почти одинаково.

Но когда вы приходите к проверкам, которые несколько более сложны, преимущество становится более заметным:

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

против.

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

Можно обсуждать, какой из них легче читать, но как только утверждение терпит неудачу, вы получите хорошее сообщение об ошибке из assertThat, но только очень минимальное количество информации из assertTrue.

assertThat расскажет вам, что такое утверждение и что вы получили. assertTrue сообщит вам, что вы получили false, где вы ожидали true.

Ответ 2

JUnit примечания к выпуску для версии 4.4 (где она была введена) содержит четыре преимущества:

  • Более читаемый и печатаемый: этот синтаксис позволяет вам думать в терминах объекта, глагола, объекта (assert "x is 3" ), а не assertEquals, который использует глагол, объект, субъект (assert "равно 3 x" )
  • Комбинации: любой оператор matcher может быть отменен (not (s)), объединенный (или (ы).or(t)), сопоставленный с коллекцией (каждый (ы)) или используемый в пользовательских комбинациях (afterFiveSeconds (ы))
  • Считываемые сообщения об ошибках. (...)
  • Пользовательские совпадения. Внедряя интерфейс Matcher самостоятельно, вы можете получить все вышеупомянутые преимущества для своих собственных утверждений.

Более подробная аргументация от парня, создавшего новый синтаксис: здесь.

Ответ 3

В основном для повышения читаемости кода.

Помимо hamcrest вы также можете использовать утверждения флага. У них несколько преимуществ по сравнению с hamcrest, например:

Некоторые примеры

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));

17 октября 2016 г. Обновление

Fest больше не активен, вместо этого используйте AssertJ.

Ответ 4

Очень простое обоснование состоит в том, что трудно испортить новый синтаксис.

Предположим, что определенное значение foo должно быть 1 после теста.

assertEqual(1, foo);

- ИЛИ -

assertThat(foo, is(1));

При первом подходе очень легко забыть правильный порядок и набрать его назад. Тогда вместо того, чтобы сказать, что тест не прошел, потому что он ожидал 1 и получил 2, сообщение обратное. Не проблема, когда тест проходит, но может привести к путанице, когда тест не удался.

Во второй версии почти невозможно сделать эту ошибку.

Ответ 5

Пример:

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!
  • вы можете сделать ваши тесты более конкретными.
  • вы получаете более подробное исключение, если тесты терпят неудачу.
  • легче прочитать тест

btw: вы можете также писать текст в assertXXX...

Ответ 6

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

Близок к естественному языку.

Легче читать, проще анализировать код. Программист тратит больше времени на анализ кода, чем на новый. Поэтому, если код будет легко анализировать, разработчик должен быть более продуктивным.

P.S. Код должен быть также хорошо написанной книгой. Самодокументированный код.

Ответ 7

есть преимущества, чтобы утверждать, что над assertEquals -
 1) более читаемый
 2) больше информации об отказе
 3) ошибки времени компиляции - а не ошибки времени выполнения
 4) гибкость при написании тестовых условий
 5) портативный - если вы используете hamcrest - вы можете использовать jUnit или TestNG в качестве базовой структуры.