// Before (AssertJ)
import static org.assertj.core.api.Assertions.*;
// After (Reality Check)
import static io.github.imetaxas.realitycheck.RealityAssertions.*; // assertThat() — same muscle memory
| AssertJ | Reality Check | Notes |
|---|---|---|
assertThat(str).isEqualTo("x") |
assertThat(str).isEqualTo("x") |
Identical with RealityAssertions |
assertThat(str).contains("x") |
assertThat(str).contains("x") |
Identical |
assertThat(str).startsWith("x") |
assertThat(str).startsWith("x") |
Identical |
assertThat(str).matches("regex") |
assertThat(str).matches("regex") |
Identical |
assertThat(num).isPositive() |
assertThat(num).isPositive() |
Identical |
assertThat(num).isBetween(1, 10) |
assertThat(num).isBetween(1, 10) |
Identical |
assertThat(num).isCloseTo(3.14, within(0.01)) |
assertThat(num).isCloseTo(3.15, 0.01) |
No within() wrapper needed |
assertThat(list).hasSize(3) |
assertThat(list).hasSize(3) |
Identical |
assertThat(list).contains("a") |
assertThat(list).contains("a") |
Identical |
assertThat(list).containsExactly("a","b") |
assertThat(list).containsExactly("a","b") |
Identical |
assertThat(map).containsKey("k") |
assertThat(map).containsKey("k") |
Identical |
assertThat(map).containsEntry("k","v") |
assertThat(map).containsEntry("k","v") |
Identical |
assertThat(opt).isPresent() |
assertThat(opt).isPresent() |
Identical |
assertThat(opt).hasValue("x") |
assertThat(opt).hasValue("x") |
Identical |
assertThat(bool).isTrue() |
assertThat(bool).isTrue() |
Identical |
assertThat(file).exists() |
assertThat(path).exists() |
Takes Path not File (also accepts File) |
assertThat(instant).isBefore(x) |
assertThat(instant).isBefore(x) |
Identical |
assertThatThrownBy(() -> ...) |
assertThatThrownBy(() -> ...) |
Identical |
.isInstanceOf(X.class) |
.isInstanceOf(X.class) |
Identical |
.hasMessage("msg") |
.hasMessage("msg") |
Identical |
.hasMessageContaining("x") |
.hasMessageContaining("x") |
Identical |
assertThat(x).satisfies(v -> ...) |
assertThat(x).satisfies(v -> ...) |
Identical — Consumer overload |
assertThat(x).matches(pred) |
assertThat(x).matches(pred) |
Identical |
| AssertJ | Reality Check | Why |
|---|---|---|
assertThat(obj).as("label") |
assertThat(obj).as("label") |
Identical — same API |
assertThat(obj).withFailMessage("…") |
assertWithMessage("…").that(obj) |
Phrased differently |
usingRecursiveComparison() |
assertThat(obj).hasSameFieldsAs(expected) |
Explicit, shallow — first-level fields only |
usingRecursiveComparison() (deep) |
assertThat(obj, MyCheck::new) |
No reflection — explicit field assertions |
assertThat(floatVal) |
assertThat(floatVal) |
Identical — float is now a first-class overload |
SoftAssertions.assertSoftly(s -> ...) |
Reality.checkAll(s -> ...) |
Same pattern, different name |
@ExtendWith(SoftAssertionsExtension.class) |
@WithSoftChecks |
Annotation name differs |
extracting(Foo::getBar) |
.satisfies(f -> assertThat(f.getBar())...) |
Use satisfies with inline checks |
AbstractAssert subclass (~30 lines) |
record MyCheck(...) implements Check (3 lines) |
Records as checks |
Condition |
satisfies(Predicate, String) |
Predicate + description |
assertThat(list).allMatch(pred) |
assertThat(list).allMatch(pred) |
Identical — label is now optional |
// Before (AssertJ)
SoftAssertions.assertSoftly(softly -> {
softly.assertThat(name).isNotEmpty();
softly.assertThat(age).isPositive();
});
// After (Reality Check)
RealityAssertions.assertAll(softly -> {
softly.assertThat(name).isNotEmpty();
softly.assertThat(age).isPositive();
});
.as())Reality Check supports the same .as("label") API as AssertJ — it works on every check type and stacks labels into soft-assertion failure reports:
// Both compile and behave identically
assertThat(user.getName()).as("user name").isEqualTo("Alice");
assertThat(user.getAge()).as("user age").isBetween(18, 99);
usingRecursiveComparison → hasSameFieldsAs)For simple POJOs and value objects, hasSameFieldsAs provides safe shallow field comparison without requiring usingRecursiveComparison:
// Before (AssertJ)
assertThat(actual).usingRecursiveComparison().isEqualTo(expected);
// After (Reality Check — explicit, first-level fields only)
assertThat(actual).hasSameFieldsAs(expected);
// On mismatch:
// field mismatch(es) in <User>:
// field 'name': expected <Bob> but was <Alice>
// field 'age': expected <25> but was <30>
For deep recursive comparison, use a custom check:
assertThat(order, OrderCheck::new).hasMatchingItems(expected.getItems());
// Before (AssertJ — ~30 lines)
public class MoneyAssert extends AbstractAssert<MoneyAssert, Money> {
public MoneyAssert(Money actual) {
super(actual, MoneyAssert.class);
}
public static MoneyAssert assertThat(Money actual) {
return new MoneyAssert(actual);
}
public MoneyAssert hasCurrency(String code) {
isNotNull();
if (!actual.getCurrency().equals(code)) {
failWithMessage("Expected currency <%s> but was <%s>", code, actual.getCurrency());
}
return this;
}
}
// After (Reality Check — 3 lines for the check, use via factory)
record MoneyCheck(Money actual, FailureHandler failureHandler) implements Check<MoneyCheck, Money> {
@Override public MoneyCheck self() { return this; }
public MoneyCheck hasCurrency(String code) {
return failureHandler.check(self(), actual.getCurrency().equals(code),
"expected currency <%s> but was <%s>", code, actual.getCurrency());
}
}
// Usage:
assertThat(payment, MoneyCheck::new).hasCurrency("USD");
// Before (Truth)
import static com.google.common.truth.Truth.assertThat;
// After (Reality Check)
import static io.github.imetaxas.realitycheck.RealityAssertions.*;
| Truth | Reality Check | Notes |
|---|---|---|
assertThat(str).isEqualTo("x") |
assertThat(str).isEqualTo("x") |
Identical |
assertThat(str).contains("x") |
assertThat(str).contains("x") |
Identical |
assertThat(str).startsWith("x") |
assertThat(str).startsWith("x") |
Identical |
assertThat(str).matches("regex") |
assertThat(str).matches("regex") |
Identical |
assertThat(num).isEqualTo(42) |
assertThat(num).isEqualTo(42) |
Identical |
assertThat(num).isGreaterThan(0) |
assertThat(num).isGreaterThan(0) |
Identical |
assertThat(num).isAtLeast(1) |
assertThat(num).isAtLeast(1) |
Identical (alias provided) |
assertThat(num).isAtMost(100) |
assertThat(num).isAtMost(100) |
Identical (alias provided) |
assertThat(list).hasSize(3) |
assertThat(list).hasSize(3) |
Identical |
assertThat(list).contains("a") |
assertThat(list).contains("a") |
Identical |
assertThat(list).containsExactly("a","b") |
assertThat(list).containsExactly("a","b") |
Identical |
assertThat(list).containsExactly(...).inOrder() |
assertThat(list).containsExactly(...) |
Always ordered in RC |
assertThat(map).containsKey("k") |
assertThat(map).containsKey("k") |
Identical |
assertThat(map).containsEntry("k","v") |
assertThat(map).containsEntry("k","v") |
Identical |
assertThat(opt).isPresent() |
assertThat(opt).isPresent() |
Identical |
assertThat(bool).isTrue() |
assertThat(bool).isTrue() |
Identical |
assertThat(x).isNull() |
assertThat(x).isNull() |
Identical |
assertThat(x).isInstanceOf(Foo.class) |
assertThat(x).isInstanceOf(Foo.class) |
Identical |
| Truth | Reality Check | Why |
|---|---|---|
No method chaining (returns void) |
Full fluent chaining | RC returns self() |
No .as("label") API |
.as("label") / .withDescription("label") |
Full label support |
assertThrows(X.class, () -> ...) (JUnit) |
assertThatThrownBy(() -> ...).isInstanceOf(X.class) |
Fluent, with chaining |
Custom Subject (~50 lines) |
record MyCheck(...) implements Check (3 lines) |
16x less boilerplate |
| Guava dependency (3 MB) | Zero dependencies (96 KB) | No Guava needed |
| JUnit 4 soft assertions only | Reality.checkAll(...) / @WithSoftChecks |
Full JUnit 5 |
No BigDecimal subject |
assertThat(bigDecimal).isCloseTo(...) |
Built in |
No Stream subject |
assertThatStream(stream).contains(...) |
Built in |
| No suppressed exceptions | .hasSuppressed().suppressedException(0) |
Built in |
No float subject |
assertThat(floatVal) |
First-class float overload |
isAtLeast / isAtMost naming// Before (Truth) — works unchanged in Reality Check
assertThat(score).isAtLeast(60);
assertThat(score).isAtMost(100);
// Verbose form also available:
assertThat(score).isGreaterThanOrEqualTo(60);
assertThat(score).isLessThanOrEqualTo(100);
// Or combine:
assertThat(score).isBetween(60, 100);
containsExactly(...).inOrder() pattern// Before (Truth)
assertThat(list).containsExactly("a", "b", "c").inOrder();
// After (Reality Check — containsExactly is always ordered)
assertThat(list).containsExactly("a", "b", "c");
// For unordered comparison:
assertThat(list).containsExactlyInAnyOrder("c", "a", "b");
After migrating, if Truth was the only reason Guava was on the test classpath, you can remove it:
<!-- Remove these -->
<dependency>
<groupId>com.google.truth</groupId>
<artifactId>truth</artifactId>
</dependency>
<!-- Guava is no longer needed for assertions -->