Можете ли вы добавить собственное сообщение в AssertJ assertThat?

90

У нас есть набор тестов, который в основном использует утверждения JUnit с сопоставителями Hamcrest. Один из наших сотрудников начал экспериментировать с AssertJ и поразил людей своим синтаксисом, гибкостью и декларативностью. JUnit предоставляет одну функцию, эквивалент которой я не могу найти в AssertJ: добавление настраиваемого сообщения об ошибке утверждения.

Мы часто сравниваем объекты, которые не предназначены для чтения человеком и будут иметь случайные идентификаторы или UUID, и невозможно определить, какими они должны быть, по данным, которые они содержат. К сожалению, это неизбежная ситуация для нашей кодовой базы, поскольку часть цели, которую она выполняет, - это сопоставление данных между другими сервисами, не обязательно понимая, что это такое.

В JUnit assertThatметод предоставляет версию с String reasonпараметром перед параметром Matcher<T>param. Это делает тривиальным добавление короткой строки отладки, проливающей некоторый свет на проблему, например, что такое сравнение должно значить для человека.

AssertJ, с другой стороны, предоставляет миллион различных обобщенныхstatic assertThat методов, которые возвращают ту или иную форму интерфейса Assert или один из множества его реализующих классов. Этот интерфейс не предоставляет стандартного способа настройки настраиваемого сообщения, которое будет включаться в сбои.

Есть ли способ получить эту функциональность из AssertJ API или одного из его расширений без необходимости создавать собственный класс assert для каждого типа assert, в который мы хотим добавлять сообщения?

Патрик М
источник

Ответы:

137

Классическим способом я нашла то, что искала, через несколько секунд после публикации вопроса. Надеюсь, это упростит поиск следующему человеку, не зная предварительно, как это называется. Магический метод - это обманчиво короткое имя as, которое является частью другого интерфейса, который AbstractAssertреализует: Descriptable , а не базовый интерфейс Assert.

public S as(String description, Object... args)

Задает описание поддерживающего String.format(String, Object...)синтаксиса этого объекта .
Пример :

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description with as() method or describedAs(), it supports String format args
  assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("[check Frodo's age] expected:<[33]> but was:<[50]>");
}

Где эта строка в кавычках в блоке catch hasMessage- это то, что отображается в журнале вывода модульного теста, если утверждение не выполняется.


Я обнаружил это, заметив failWithMessageпомощника на настраиваемой странице утверждения, на которую ссылается вопрос. JavaDoc для этого метода указывает на то , что он защищен, поэтому он не может использоваться абонентами для установки специального сообщения. Однако он упоминает asпомощника:

Более того, этот метод учитывает любое описание, заданное с помощью as(String, Object...)или заменяющее сообщение об ошибке, определенное пользователем с помощью overridingErrorMessage(String, Object...).

... и overridingErrorMessage помощник, который полностью заменяет стандартный AssertJ expected: ... but was:...сообщение с новой строкой , указанной.

На домашней странице AssertJ не упоминается ни один из помощников до тех пор, пока не будет выделена страница функций, на которой показаны примеры asпомощника в разделе « Мягкие утверждения », но напрямую не описано, что он делает.

Патрик М
источник
23

Чтобы добавить еще один вариант к ответу Патрика М:

Вместо использования Descriptable.asвы также можете использовать AbstractAssert.withFailMessage():

try {
  // set a bad age to Mr Frodo which is really 33 years old.
  frodo.setAge(50);
  // you can specify a test description via withFailMessage(), supports String format args
  assertThat(frodo.getAge()).
    withFailMessage("Frodo's age is wrong: %s years, difference %s years",
      frodo.getAge(), frodo.getAge()-33).
    isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("Frodo's age is wrong: 50 years, difference 17 years");
}

Отличие от использования в Descriptable.asтом, что оно дает вам полный контроль над настраиваемым сообщением - здесь нет «ожидалось» и «но было».

Это полезно, когда фактические тестируемые значения не используются для презентации - этот метод позволяет вам вместо этого показать другие, возможно, рассчитанные значения или вообще не отображать.


Обратите внимание, что Descriptable.asвы должны вызывать withFailMessage() перед любыми фактическими утверждениями - в противном случае это не сработает, поскольку сначала сработает утверждение. Это отмечено в Javadoc.

Sleske
источник
3
"вы должны вызвать withFailMessage () перед любыми фактическими утверждениями" спасибо, это меня сбило с толку . Порядок обзвона withFailMessageдела; Мне нравится AssertJ, но это отстой.
Abhijit Sarkar
0

Используйте встроенный as()метод в AssertJ. Например:

 assertThat(myTest).as("The test microservice is not active").isEqualTo("active");
Testilla
источник