Type-specific assertions
AssertJ provides rich, expressive assertions tailored to specific types. These specialized assertions make your tests more readable and provide better failure messages compared to generic boolean checks.
Collection assertions
AssertJ offers numerous assertions specifically designed for collections, going far beyond simple size checks.
- Before
- After
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class CollectionAssertions {
List<String> languages = List.of("Java", "Python", "JavaScript", "Kotlin");
@Test
void collection() {
assertFalse(languages.isEmpty());
assertEquals(4, languages.size());
assertTrue(languages.contains("Java"));
assertTrue(languages.containsAll(List.of("Java", "Kotlin")));
assertFalse(languages.contains("Ruby"));
}
}
Multiple separate assertions are verbose and don't provide context about the collection being tested.
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class CollectionAssertions {
List<String> languages = List.of("Java", "Python", "JavaScript", "Kotlin");
@Test
void collection() {
assertThat(languages)
.isNotEmpty()
.hasSize(4)
.contains("Java", "Kotlin")
.doesNotContain("Ruby")
.startsWith("Java")
.endsWith("Kotlin");
}
}
AssertJ's collection assertions are chainable, expressive, and provide detailed failure messages showing the actual collection contents.
Advanced collection assertions
- Before
- After
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class AdvancedCollectionAssertions {
List<Integer> numbers = List.of(2, 4, 6, 8, 10);
@Test
void allMatch() {
boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0);
assertTrue(allEven);
boolean anyGreaterThan5 = numbers.stream().anyMatch(n -> n > 5);
assertTrue(anyGreaterThan5);
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);
assertTrue(noneNegative);
}
}
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class AdvancedCollectionAssertions {
List<Integer> numbers = List.of(2, 4, 6, 8, 10);
@Test
void allMatch() {
assertThat(numbers)
.allMatch(n -> n % 2 == 0, "all numbers are even")
.anyMatch(n -> n > 5)
.noneMatch(n -> n < 0);
}
}
AssertJ eliminates the need for manual stream operations and provides clear descriptions in the assertion chain.
Date and time assertions
Testing temporal values requires careful handling of precision and timezones. AssertJ provides specialized assertions that make date comparisons intuitive.
- Before
- After
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
class DateAssertions {
LocalDateTime now = LocalDateTime.now();
LocalDate today = LocalDate.now();
@Test
void dates() {
assertTrue(now.isAfter(LocalDateTime.now().minusDays(1)));
assertTrue(now.isBefore(LocalDateTime.now().plusDays(1)));
assertEquals(2025, today.getYear());
assertTrue(today.getMonthValue() >= 1 && today.getMonthValue() <= 12);
}
}
Manual date comparisons are verbose and error-prone, especially when checking ranges or specific components.
import org.junit.jupiter.api.Test;
import java.time.LocalDate;
import java.time.LocalDateTime;
import static org.assertj.core.api.Assertions.assertThat;
class DateAssertions {
LocalDateTime now = LocalDateTime.now();
LocalDate today = LocalDate.now();
@Test
void dates() {
assertThat(now)
.isAfter(LocalDateTime.now().minusDays(1))
.isBefore(LocalDateTime.now().plusDays(1))
.hasYear(today.getYear());
assertThat(today)
.hasYear(2025)
.isToday()
.isBetween(LocalDate.of(2025, 1, 1), LocalDate.of(2025, 12, 31));
}
}
AssertJ's temporal assertions handle comparisons naturally and provide methods for checking specific date components.
Date tolerance assertions
- Before
- After
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.*;
class DateToleranceAssertions {
@Test
void timestampWithinTolerance() {
LocalDateTime expected = LocalDateTime.of(2025, 10, 7, 12, 0, 0);
LocalDateTime actual = LocalDateTime.of(2025, 10, 7, 12, 0, 3);
Duration diff = Duration.between(expected, actual);
assertTrue(Math.abs(diff.getSeconds()) <= 5);
}
}
import org.junit.jupiter.api.Test;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.within;
class DateToleranceAssertions {
@Test
void timestampWithinTolerance() {
LocalDateTime expected = LocalDateTime.of(2025, 10, 7, 12, 0, 0);
LocalDateTime actual = LocalDateTime.of(2025, 10, 7, 12, 0, 3);
assertThat(actual).isCloseTo(expected, within(5, ChronoUnit.SECONDS));
}
}
AssertJ's isCloseTo()
with temporal units provides clear, readable tolerance-based date comparisons.
File and path assertions
Testing file system operations benefits greatly from AssertJ's specialized assertions for files and paths.
- Before
- After
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.junit.jupiter.api.Assertions.*;
class FileAssertions {
Path configFile = Path.of("config.properties");
@Test
void file() throws IOException {
assertTrue(Files.exists(configFile));
assertTrue(Files.isRegularFile(configFile));
assertFalse(Files.isDirectory(configFile));
assertTrue(Files.isReadable(configFile));
assertFalse(Files.size(configFile) == 0);
assertEquals(".properties", getExtension(configFile.toString()));
}
String getExtension(String filename) {
return filename.substring(filename.lastIndexOf('.'));
}
}
File checks require verbose Files
utility calls and manual extension parsing.
import org.junit.jupiter.api.Test;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
class FileAssertions {
Path configFile = Path.of("config.properties");
@Test
void file() {
assertThat(configFile)
.exists()
.isRegularFile()
.isNotEmptyFile()
.isReadable()
.hasExtension("properties")
.hasParent(Path.of("."));
}
}
AssertJ's file assertions provide chainable, expressive checks that handle common file system operations elegantly.
File content assertions
- Before
- After
import org.junit.jupiter.api.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class FileContentAssertions {
Path logFile = Path.of("app.log");
@Test
void fileContent() throws IOException {
String content = Files.readString(logFile);
assertTrue(content.contains("ERROR"));
List<String> lines = Files.readAllLines(logFile);
assertTrue(lines.stream().anyMatch(line -> line.contains("ERROR")));
}
}
import org.junit.jupiter.api.Test;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
class FileContentAssertions {
Path logFile = Path.of("app.log");
@Test
void fileContent() {
assertThat(logFile)
.content()
.contains("ERROR");
assertThat(logFile)
.usingCharset("UTF-8")
.hasContent("expected content"); // exact match;
}
}
AssertJ can directly assert on file contents without manual reading, and chains with string assertions.
Map assertions
Maps have their own set of specialized assertions for keys, values, and entries.
- Before
- After
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.*;
class MapAssertions {
Map<String, Integer> scores = Map.of(
"Alice", 95,
"Bob", 87,
"Charlie", 92
);
@Test
void map() {
assertFalse(scores.isEmpty());
assertEquals(3, scores.size());
assertTrue(scores.containsKey("Alice"));
assertEquals(95, scores.get("Alice"));
assertTrue(scores.containsValue(87));
}
}
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.entry;
class MapAssertions {
Map<String, Integer> scores = Map.of(
"Alice", 95,
"Bob", 87,
"Charlie", 92
);
@Test
void map() {
assertThat(scores)
.isNotEmpty()
.hasSize(3)
.containsKey("Alice")
.containsValue(87)
.containsEntry("Alice", 95)
.contains(entry("Bob", 87), entry("Charlie", 92))
.doesNotContainKey("David");
}
}
AssertJ's map assertions allow testing keys, values, and entries in a fluent, chainable style with clear failure messages.
String assertions
String assertions go beyond simple equality checks to offer pattern matching, case handling, and content validation.
- Before
- After
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class StringAssertions {
String email = "user@example.com";
@Test
void string() {
assertFalse(email.isEmpty());
assertTrue(email.contains("@"));
assertTrue(email.startsWith("user"));
assertTrue(email.endsWith(".com"));
assertTrue(email.matches(".*@.*\\..*"));
}
}
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
class StringAssertions {
String email = "user@example.com";
@Test
void string() {
assertThat(email)
.isNotEmpty()
.contains("@")
.startsWith("user")
.endsWith(".com")
.matches(".*@.*\\..*")
.containsOnlyOnce("@")
.doesNotContain(" ");
}
}
AssertJ's string assertions provide intuitive methods for common string validations without manual boolean checks.