Перейти к основному содержимому

Пользовательские утверждения с помощью AssertJ

· 5 мин. чтения

1. Обзор

В этом руководстве мы рассмотрим создание пользовательских утверждений AssertJ ; основы AssertJ можно найти здесь.

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

2. Тестируемый класс

Тестовые случаи в этом руководстве будут построены вокруг класса Person :

public class Person {
private String fullName;
private int age;
private List<String> nicknames;

public Person(String fullName, int age) {
this.fullName = fullName;
this.age = age;
this.nicknames = new ArrayList<>();
}

public void addNickname(String nickname) {
nicknames.add(nickname);
}

// getters
}

3. Пользовательский класс утверждения

Написать собственный класс утверждений AssertJ довольно просто. Все, что нам нужно сделать, это объявить класс, который расширяет AbstractAssert , добавить необходимый конструктор и предоставить пользовательские методы утверждения.

Класс утверждения должен расширять класс AbstractAssert , чтобы предоставить нам доступ к основным методам утверждения API, таким как isNotNull и isEqualTo .

Вот скелет пользовательского класса утверждений для Person :

public class PersonAssert extends AbstractAssert<PersonAssert, Person> {

public PersonAssert(Person actual) {
super(actual, PersonAssert.class);
}

// assertion methods described later
}

Мы должны указать два аргумента типа при расширении класса AbstractAssert : первый — это сам класс пользовательского утверждения, который требуется для цепочки методов, а второй — тестируемый класс.

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

public static PersonAssert assertThat(Person actual) {
return new PersonAssert(actual);
}

Далее мы рассмотрим несколько пользовательских утверждений, включенных в класс PersonAssert .

Первый метод проверяет, соответствует ли полное имя человека строковому аргументу :

public PersonAssert hasFullName(String fullName) {
isNotNull();
if (!actual.getFullName().equals(fullName)) {
failWithMessage("Expected person to have full name %s but was %s",
fullName, actual.getFullName());
}
return this;
}

Следующий метод проверяет, является ли Person взрослым в зависимости от его возраста :

public PersonAssert isAdult() {
isNotNull();
if (actual.getAge() < 18) {
failWithMessage("Expected person to be adult");
}
return this;
}

Последняя проверка на существование никнейма :

public PersonAssert hasNickName(String nickName) {
isNotNull();
if (!actual.getNickNames().contains(nickName)) {
failWithMessage("Expected person to have nickname %s",
nickName);
}
return this;
}

При наличии более одного пользовательского класса утверждений мы можем обернуть все методы assertThat в класс, предоставив статический фабричный метод для каждого из классов утверждений:

public class Assertions {
public static PersonAssert assertThat(Person actual) {
return new PersonAssert(actual);
}

// static factory methods of other assertion classes
}

Показанный выше класс Assertions является удобной точкой входа для всех пользовательских классов утверждений.

Статические методы этого класса имеют одинаковое имя и отличаются друг от друга типом параметра.

4. В действии

Следующие тестовые примеры иллюстрируют пользовательские методы утверждений, которые мы создали в предыдущем разделе. Обратите внимание, что метод assertThat импортируется из нашего пользовательского класса Assertions , а не из основного API AssertJ.

Вот как можно использовать метод hasFullName :

@Test
public void whenPersonNameMatches_thenCorrect() {
Person person = new Person("John Doe", 20);
assertThat(person)
.hasFullName("John Doe");
}

Это отрицательный тестовый пример, иллюстрирующий метод isAdult :

@Test
public void whenPersonAgeLessThanEighteen_thenNotAdult() {
Person person = new Person("Jane Roe", 16);

// assertion fails
assertThat(person).isAdult();
}

и еще один тест, демонстрирующий метод hasNickname :

@Test
public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() {
Person person = new Person("John Doe", 20);
person.addNickname("Nick");

// assertion will fail
assertThat(person)
.hasNickname("John");
}

5. Генератор утверждений

Написание пользовательских классов утверждений, соответствующих объектной модели, прокладывает путь к очень читабельным тестам.

Однако, если у нас много классов, было бы мучительно вручную создавать пользовательские классы утверждений для всех из них . Здесь в игру вступает генератор утверждений AssertJ.

Чтобы использовать генератор утверждений с Maven, нам нужно добавить плагин в файл pom.xml :

<plugin>
<groupId>org.assertj</groupId>
<artifactId>assertj-assertions-generator-maven-plugin</artifactId>
<version>2.1.0</version>
<configuration>
<classes>
<param>com.foreach.testing.assertj.custom.Person</param>
</classes>
</configuration>
</plugin>

Последнюю версию assertj-assertions-generator-maven-plugin можно найти здесь .

Элемент классов в приведенном выше плагине помечает классы, для которых мы хотим генерировать утверждения. Пожалуйста, смотрите этот пост для других конфигураций плагина.

Генератор утверждений AssertJ создает утверждения для каждого общедоступного свойства целевого класса . Конкретное имя каждого метода утверждения зависит от типа поля или свойства. Полное описание генератора утверждений можно найти в этой ссылке .

Выполните следующую команду Maven в базовом каталоге проекта:

mvn assertj:generate-assertions

Мы должны увидеть классы утверждений, сгенерированные в папке target /generated-test-sources/assertj-assertions . Например, сгенерированный класс точки входа для сгенерированных утверждений выглядит так:

// generated comments are stripped off for brevity

package com.foreach.testing.assertj.custom;

@javax.annotation.Generated(value="assertj-assertions-generator")
public class Assertions {

@org.assertj.core.util.CheckReturnValue
public static com.foreach.testing.assertj.custom.PersonAssert
assertThat(com.foreach.testing.assertj.custom.Person actual) {
return new com.foreach.testing.assertj.custom.PersonAssert(actual);
}

protected Assertions() {
// empty
}
}

Теперь мы можем скопировать сгенерированные исходные файлы в тестовый каталог, а затем добавить пользовательские методы утверждения, чтобы удовлетворить наши требования к тестированию.

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

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

6. Заключение

В этом руководстве мы показали, как создавать собственные утверждения для создания читаемого тестового кода с библиотекой AssertJ как вручную, так и автоматически.

Если у нас есть только небольшое количество тестируемых классов, ручного решения достаточно; в противном случае следует использовать генератор.

И, как всегда, реализацию всех примеров и фрагментов кода можно найти на GitHub .