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

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

 

1. обзор

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

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

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

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

public class Person {
    private String fullName;
    private int age;
    private List 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 довольно просто. All we need to do is to declare a class that extends AbstractAssert, add a required constructor, and provide custom assertion methods.с

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

Вот скелет настраиваемого класса утверждения дляPerson:

public class PersonAssert extends AbstractAssert {

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

    // assertion methods described later
}

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

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

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

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

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

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 взрослым, на основе егоage:

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

Последний проверяет наличиеnickname:

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. Генератор утверждений

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

However, if we have a lot of classes, it would be painful to manually create custom assertion classes for all of them. Именно здесь в игру вступает генератор утверждений AssertJ.

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


    org.assertj
    assertj-assertions-generator-maven-plugin
    2.1.0
    
        
            com.example.testing.assertj.custom.Person
        
    

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

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

The AssertJ assertions generator creates assertions for each public property of the target class. Конкретное имя каждого метода утверждения зависит от типа поля или свойства. Полное описание генератора утверждений см. Вthis reference.

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

mvn assertj:generate-assertions

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

// generated comments are stripped off for brevity

package com.example.testing.assertj.custom;

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

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

    protected Assertions() {
        // empty
    }
}

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

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

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

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

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

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

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