Как писать проверки быстро

Сегодня продолжу разговор о том, как писать автотесты быстро. Мы уже разобрались, как очень быстро и эффективно конвертировать REST ответы в Java объекты.

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

Еще пару лет назад для написания ассертов я активно использовал библиотеку Hamcrest Matchers. Классная библиотека, которая отлично справляется со своими задачами, пока дело не доходит до создания матчеров для своих кастомных классов.

Вот, к примеру, у нас есть класс:

class User{
    String name;
    String password;
    List<String> phoneNumbers;
}

Используя Hamcrest, мы можем написать:

public void testUserInfo(){
    User user = when().get("/users").then().extract().response().as(User.class);

    assertThat(user.name, equalTo("name"))
    assertThat(user.password, equalTo("test"))
    assertThat(user.phoneNumbers, hasItem("+1(234)567"))
}

Достаточно неплохо, если вам нужно написать такой код в одном тесте и для одного объекта. Hamcrest позволяет писать кастомные матчеры. Но писать матчеры руками - занятие унылое. Поверьте мне, я пробовал. Польза в этом одна: вы начинаете понимать, как библиотека работает внутри. Благо, в Github можно найти утилиту, которая позволяет генерировать матчеры.

Работает она достаточно просто: берем свой класс, ставим над нужными полями аннотацию @GenerateMatcher, запускаем генерилку и на выходе получаем готовые матчеры.

Используя эту супервозможность, мы можем написать такой код:

public void testUserInfo(){
    User user = when().get("/users").then().extract().response().as(User.class);

    assertThat(user, hasName("name"))
    assertThat(user, hasPassword("test"))
    assertThat(user, hasPhoneNumberItem("+1(234)567"))
}

Хорошо. Но идти и руками ставить аннотации - скукотища! Да и генерилка работает только в связке с Maven. Можно сделать гораздо круче, но для этого нужно сменить знакомый нам Hamcrest на Assertj.

Отмечу, что синтаксис assertj отличается от того, который мы писали с Hamcrest. Поэтому при переходе вам нужно будет переписать много кода.

Assertj тоже позволяет генерировать матчеры для Java классов. Радует, что для этого есть плагины как для Maven, так и для Gradle. В документации достаточно хорошо описаны способы подключения плагинов.

С помощью assertj assertion generator мы можем генерировать матчеры для любого класса, просто указав путь к пакету, без какой-либо надобности ставить дополнительные аннотации. Для меня это архиважно, так как не всегда есть возможность менять код доменных объектов.

Давайте посмотрим, как изменится код тестов при использовании assertj:

public void testUserInfo(){
    User user = when().get("/users").then().extract().response().as(User.class);

    UserAssert.assertThat(user)
                .hasName("user")
                .hasPassword("test")
                .hasPhoneNumberItem("+1(234)567");
}

Чем такой подход круче?

Вы генерируете 80% кода автоматически. Остается написать вызов нужных методов RestAssured и соответствующих проверок. В случае, если ваша доменная модель меняется - скажем, какое-то поле удаляется или меняет тип - все, что нужно будет сделать, - это вызвать ./gradlew generateJsonSchema2Pojo assertjGen и код автоматически обновится. Вам останется немного подправить тесты. Я такой подход успешно использую на своем текущем проекте - работает просто шикарно. Рекомендую попробовать - вам понравится.