Подтвердить что ты не робот

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

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

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

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

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

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

4b9b3361

Ответ 1

И в классическом стиле я нашел то, что искал моменты после публикации вопроса. Надеюсь, это облегчит поиск следующего человека, не дав сначала знать, что он назвал. Магический метод - обманчиво коротко названный 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 age", frodo.getName()).isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("[check Frodo age] expected:<[33]> but was:<[50]>");
}

Если указанная строка в блоке catch hasMessage - это то, что появляется в вашем журнале вывода unit test, если утверждение не выполнено.


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

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

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

На домашней странице AssertJ не упоминается ни один из помощников, пока объекты не выделяют страницы, где показаны примеры as помощника в Soft Assertions, но напрямую не описывает, что он делает.

Ответ 2

К вашему сведению, это задокументировано на новом веб-сайте AssertJ (который все еще находится в стадии разработки, но уже содержит полезную информацию), см. Https://assertj.github.io/doc/#assertj-core-assertion-description.

Ответ 3

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

Вместо использования 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 age is wrong: %s years, difference %s years",
      frodo.getAge(), frodo.getAge()-33).
    isEqualTo(33);
} catch (AssertionError e) {
  assertThat(e).hasMessage("Frodo age is wrong: 50 years, difference 17 years");
}

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

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


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