Files
awesome-copilot/skills/spring-boot-testing/references/assertj-basics.md
Kartik Dhiman e4fc57f204 feat: add spring-boot-testing skill for Spring Boot 4.0 (#1085)
- Introduced MockMvcTester for AssertJ-style assertions in Spring MVC testing.
- Added @RestClientTest for testing REST clients with MockRestServiceServer.
- Implemented RestTestClient as a modern alternative to TestRestTemplate.
- Documented migration steps from Spring Boot 3.x to 4.0, including dependency and annotation changes.
- Created an overview of test slices to guide testing strategies.
- Included Testcontainers setup for JDBC testing with PostgreSQL and MySQL.
- Enhanced @WebMvcTest documentation with examples for various HTTP methods and validation.
2026-03-20 10:24:37 +11:00

4.3 KiB

AssertJ Basics

Fluent assertions for readable, maintainable tests.

Basic Assertions

Object Equality

assertThat(order.getStatus()).isEqualTo("PENDING");
assertThat(order.getId()).isNotEqualTo(0);
assertThat(order).isEqualTo(expectedOrder);
assertThat(order).isNotNull();
assertThat(nullOrder).isNull();

String Assertions

assertThat(order.getDescription())
  .isEqualTo("Test Order")
  .startsWith("Test")
  .endsWith("Order")
  .contains("Test")
  .hasSize(10)
  .matches("[A-Za-z ]+");

Number Assertions

assertThat(order.getAmount())
  .isEqualTo(99.99)
  .isGreaterThan(50)
  .isLessThan(100)
  .isBetween(50, 100)
  .isPositive()
  .isNotZero();

Boolean Assertions

assertThat(order.isActive()).isTrue();
assertThat(order.isDeleted()).isFalse();

Date/Time Assertions

assertThat(order.getCreatedAt())
  .isEqualTo(LocalDateTime.of(2024, 1, 15, 10, 30))
  .isBefore(LocalDateTime.now())
  .isAfter(LocalDateTime.of(2024, 1, 1))
  .isCloseTo(LocalDateTime.now(), within(5, ChronoUnit.SECONDS));

Optional Assertions

Optional<Order> maybeOrder = orderService.findById(1L);

assertThat(maybeOrder)
  .isPresent()
  .hasValueSatisfying(order -> {
    assertThat(order.getId()).isEqualTo(1L);
  });

assertThat(orderService.findById(999L)).isEmpty();

Exception Assertions

JUnit 5 Exception Handling

@Test
void shouldThrowException() {
  OrderService service = new OrderService();
  
  assertThatThrownBy(() -> service.findById(999L))
    .isInstanceOf(OrderNotFoundException.class)
    .hasMessage("Order 999 not found")
    .hasMessageContaining("999");
}

AssertJ Exception Handling

@Test
void shouldThrowExceptionWithCause() {
  assertThatExceptionOfType(OrderProcessingException.class)
    .isThrownBy(() -> service.processOrder(invalidOrder))
    .withCauseInstanceOf(ValidationException.class);
}

Custom Assertions

Create domain-specific assertions for reusable test code:

public class OrderAssert extends AbstractAssert<OrderAssert, Order> {
  
  public static OrderAssert assertThat(Order actual) {
    return new OrderAssert(actual);
  }
  
  private OrderAssert(Order actual) {
    super(actual, OrderAssert.class);
  }
  
  public OrderAssert isPending() {
    isNotNull();
    if (!"PENDING".equals(actual.getStatus())) {
      failWithMessage("Expected order status to be PENDING but was %s", actual.getStatus());
    }
    return this;
  }
  
  public OrderAssert hasTotal(BigDecimal expected) {
    isNotNull();
    if (!expected.equals(actual.getTotal())) {
      failWithMessage("Expected total %s but was %s", expected, actual.getTotal());
    }
    return this;
  }
}

Usage:

OrderAssert.assertThat(order)
  .isPending()
  .hasTotal(new BigDecimal("99.99"));

Soft Assertions

Collect multiple failures before failing:

@Test
void shouldValidateOrder() {
  Order order = orderService.findById(1L);
  
  SoftAssertions.assertSoftly(softly -> {
    softly.assertThat(order.getId()).isEqualTo(1L);
    softly.assertThat(order.getStatus()).isEqualTo("PENDING");
    softly.assertThat(order.getItems()).isNotEmpty();
  });
}

Satisfies Pattern

assertThat(order)
  .satisfies(o -> {
    assertThat(o.getId()).isPositive();
    assertThat(o.getStatus()).isNotBlank();
    assertThat(o.getCreatedAt()).isNotNull();
  });

Using with Spring

import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest
class OrderServiceTest {
  
  @Autowired
  private OrderService orderService;
  
  @Test
  void shouldCreateOrder() {
    Order order = orderService.create(new OrderRequest("Product", 2));
    
    assertThat(order)
      .isNotNull()
      .extracting(Order::getId, Order::getStatus)
      .containsExactly(1L, "PENDING");
  }
}

Static Import

Always use static import for clean assertions:

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.catchThrowable;

Key Benefits

  1. Readable: Sentence-like structure
  2. Type-safe: IDE autocomplete works
  3. Rich API: Many built-in assertions
  4. Extensible: Custom assertions for your domain
  5. Better Errors: Clear failure messages