← Назад к вопросам

Какие плюсы и минусы AssertJ?

1.0 Junior🔥 71 комментариев
#Тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Плюсы и минусы AssertJ

AssertJ это современная библиотека для написания читаемых assertion'ов в тестах. Я использую её в 100% своих проектов, и это значительно улучшило качество тестов.

1. Что такое AssertJ

AssertJ предоставляет fluent API для assertion'ов вместо стандартного JUnit:

// Стандартный JUnit (скучно и нечитаемо)
assertTrue(user.getAge() > 18);
assertEquals(user.getName(), "John");
assertNull(user.getEmail());

// AssertJ (читаемо и выразительно)
assertThat(user.getAge())
    .isPositive()
    .isGreaterThan(18);
assertThat(user.getName())
    .isEqualTo("John")
    .isNotBlank()
    .hasLength(4);
assertThat(user.getEmail())
    .isNull();

2. Плюсы AssertJ

1. Читаемость кода:

AssertJ читается как предложение на английском:

// Очень естественно
assertThat(user)
    .isNotNull()
    .extracting(User::getName)
    .isEqualTo("John");

// Vs JUnit (нечитаемо)
assertNotNull(user);
assertEquals(user.getName(), "John");

2. Лучшие error сообщения:

// AssertJ:
List<Integer> actual = Arrays.asList(1, 2, 3);
assertThat(actual).contains(5);

// Сообщение об ошибке:
// Expecting:
//   <[1, 2, 3]>
// to contain:
//   <[5]>
// but could not find:
//   <[5]>

// JUnit:
assertTrue(actual.contains(5));
// Сообщение: "assertion failed"

3. Fluent API (цепочка методов):

assertThat("hello")
    .isNotEmpty()           // String методы
    .hasSize(5)
    .startsWith("hel")
    .endsWith("lo")
    .contains("ll")
    .doesNotContain("x");

4. Проверка collections просто:

List<User> users = getUsers();

// Проверить размер
assertThat(users).hasSize(3);

// Проверить наличие элемента
assertThat(users).contains(user1, user2);

// Проверить элементы по условию
assertThat(users)
    .filteredOn(u -> u.getAge() > 18)
    .hasSize(2);

// Проверить поля
assertThat(users)
    .extracting(User::getName)
    .contains("John", "Jane");

// Сложные проверки
assertThat(users)
    .filteredOn(u -> u.isActive())
    .extracting(User::getEmail)
    .allMatch(email -> email.contains("@"));

5. Optional и Stream поддержка:

Optional<User> user = findUser();
assertThat(user)
    .isPresent()
    .hasValue(expectedUser);

assertThat(Optional.empty())
    .isEmpty();

Stream<Integer> stream = Stream.of(1, 2, 3);
assertThat(stream).contains(2);

6. Custom assertions легко:

// Можно расширить
public class UserAssertions extends AbstractAssert<UserAssertions, User> {
    public UserAssertions isAdult() {
        isNotNull();
        if (actual.getAge() < 18) {
            failWithMessage("User is not an adult");
        }
        return this;
    }
}

// Использование
assertThat(user)
    .isNotNull()
    .isAdult();

7. Условные assertion'ы (soft assertions):

// Все assertion'ы выполняются, errors собираются
SoftAssertions softly = new SoftAssertions();
softly.assertThat(user.getName()).isEqualTo("Wrong");
softly.assertThat(user.getAge()).isEqualTo(99);
softly.assertThat(user.getEmail()).isNull();
softly.assertAll();  // Выкинет все ошибки разом

// Или более новый стиль
assertThatObject(user)
    .satisfies(u -> assertThat(u.getName()).isEqualTo("John"))
    .satisfies(u -> assertThat(u.getAge()).isGreaterThan(18));

3. Минусы AssertJ

1. Зависимость добавляется:

<!-- pom.xml -->
<dependency>
    <groupId>org.assertj</groupId>
    <artifactId>assertj-core</artifactId>
    <version>3.24.1</version>
    <scope>test</scope>
</dependency>

Это не проблема, но добавляет jar в classpath.

2. Кривая обучения:

Способов что-то проверить множество, новички запутаются:

// Много вариантов для одного
assertThat(value).isEqualTo(expected);
assertThat(value).as("value").isEqualTo(expected);
assertThat(value).withFailMessage("Failed").isEqualTo(expected);

3. IDE auto-complete может быть медленным:

Большой fluent API означает много методов, IDE может тормозить.

4. Нетипизированные коллекции сложны:

List raw = getRawList();  // Object list

// Типизировать сложновато
assertThat(raw)
    .asInstanceOf(InstanceOfAssertFactories.list(
        InstanceOfAssertFactories.type(String.class)))
    .contains("value");

5. Нет встроенной поддержки некоторых типов:

Для custom классов нужно писать extractors или assertions.

4. AssertJ vs JUnit

АспектAssertJJUnit
ЧитаемостьОтличнаяПлохая
Error сообщенияДетальныеМинимальные
APIFluentПростой
CollectionsМощнаяБазовая
ТипизацияХорошаяНет
ОбучениеMediumEasy

5. Best practices AssertJ

1. Используй extracting для вложенных объектов:

List<User> users = getUsers();

assertThat(users)
    .extracting(User::getName, User::getAge)
    .containsExactly(
        tuple("John", 30),
        tuple("Jane", 25)
    );

2. Используй filteredOn для условных проверок:

assertThat(users)
    .filteredOn(u -> u.getAge() > 18)
    .as("adults")
    .hasSize(5);

3. Описывай what you're testing:

// Хорошо
assertThat(user.getStatus())
    .as("user status after payment")
    .isEqualTo("PAID");

// Плохо
assertThat(user.getStatus())
    .isEqualTo("PAID");

4. Комбинируй assertions логично:

// Хорошо
assertThat(user)
    .isNotNull()
    .satisfies(u -> {
        assertThat(u.getName()).isNotBlank();
        assertThat(u.getAge()).isPositive();
    });

6. Интеграция с другими библиотеками

AssertJ + Mockito:

Mock<UserRepository> mockRepo = mock(UserRepository.class);

assertThat(mockRepo)
    .hasBeenCalledTimes(1)
    .with(user);

// Проверка call arguments
assertThat(mockRepo.getUser(userId))
    .extracting(User::getName)
    .isEqualTo("John");

AssertJ + Spring:

@Test
void testEndpoint() {
    var response = webTestClient.get()
        .uri("/users/1")
        .exchange();
    
    assertThat(response.getStatus())
        .isEqualTo(200);
    
    assertThat(response.getBody())
        .extracting(User::getName)
        .isEqualTo("John");
}

7. Вывод

AssertJ это modern standard для Java тестов. Я рекомендую использовать его везде:

Плюсы перевешивают минусы:

  • Тесты более читаемы
  • Ошибки более понятны
  • Development faster
  • Maintenance easier

Минусы минимальны:

  • Одна зависимость (не проблема)
  • Кривая обучения небольшая

Мой совет: Если в проекте используется JUnit assertions, предложи мигрировать на AssertJ. Это улучшит качество и читаемость всех тестов в проекте. За 10+ лет я вижу что проекты с AssertJ имеют лучшие тесты.