A fluent assertion library for Java 17+ with first-class support for JSON, CSV, XML, YAML, URIs, snapshot testing, and more.
Quick Start · Full Usage Guide · Migration from AssertJ / Truth · Roadmap · Javadoc
Assertion missing? Open an issue — contributions are welcome!
Maven:
<dependency>
<groupId>io.github.imetaxas</groupId>
<artifactId>realitycheck-core</artifactId>
<version>1.0.0</version>
<scope>test</scope>
</dependency>Gradle (Kotlin DSL):
testImplementation("io.github.imetaxas:realitycheck-core:1.0.0")Gradle (Groovy DSL):
testImplementation 'io.github.imetaxas:realitycheck-core:1.0.0'Using multiple modules? See the BOM setup to manage versions in one place.
import static io.github.imetaxas.realitycheck.RealityAssertions.*;
import static io.github.imetaxas.realitycheck.json.JsonReality.*;
import org.junit.jupiter.api.Test;
class QuickStartTest {
@Test
void strings() {
assertThat("hello world").isNotEmpty().startsWith("hello").hasLength(11);
}
@Test
void json() {
String response = "{\"user\":{\"name\":\"Alice\",\"roles\":[\"admin\"]}}";
assertThatJson(response)
.isValidJson()
.fieldEquals("user.name", "Alice")
.fieldIsArray("user.roles");
}
@Test
void exceptions() {
assertThatThrownBy(() -> Integer.parseInt("oops"))
.isInstanceOf(NumberFormatException.class)
.hasMessageContaining("oops");
}
@Test
void softAssertions() {
String name = "Alice";
int age = 30;
String email = "alice@example.com";
assertAll(softly -> {
softly.assertThat(name).isNotEmpty();
softly.assertThat(age).isPositive();
softly.assertThat(email).contains("@");
});
}
}Coming from AssertJ or Truth?
assertThatworks out of the box — same muscle memory, zero friction. See the migration guide.
assertThat("hello").isEqualTo("world");
→ expected: <world> but was: <hello>
assertThatJson(json).fieldEquals("user.name", "Bob"); // requires realitycheck-json
→ expected field <user.name> = <Bob> but was: <Alice>
assertThatSnapshot(response).matchesSnapshot(...); // requires realitycheck-snapshot
→ snapshot differs:
- "status": "ok"
+ "status": "error"
| Feature | JUnit 5 | Google Truth | AssertJ | Reality Check |
|---|---|---|---|---|
| JSON structural diff | — | — | — | ✅ |
| CSV assertions (RFC 4180) | — | — | — | ✅ |
| XML assertions (XPath, XXE-safe) | — | — | — | ✅ |
| YAML assertions (dot-path) | — | — | — | ✅ |
| Snapshot / golden-file testing | — | — | — | ✅ |
| Map dot-path navigation | — | — | — | ✅ |
| Regex capture group assertions | — | — | — | ✅ |
| URI/URL component assertions | — | — | Limited | ✅ |
| Multiline diff in failure messages | — | — | — | ✅ |
| Execution timing assertions | — | — | — | ✅ |
| Exception cause chain traversal | — | Limited | Limited | ✅ |
| Suppressed exception access | — | Missing | — | ✅ |
| Thread-safe soft assertions | ❌ (stateless) | JUnit 4 only | Buggy | ✅ |
| Fluent method chaining | ❌ | No | ✅ | ✅ |
| Zero-boilerplate custom extension | — | ~50 lines | ~30 lines | 3 lines |
| Zero runtime dependencies (core) | ✅ | ❌ (Guava) | ✅ | ✅ |
assertThat() drop-in alias |
— | ✅ | ✅ | ✅ |
| Modern Java (17+, records, sealed) | Java 8 | Java 8 | Java 8 | Java 17+ |
| Module | Artifact ID | What it adds | Extra deps |
|---|---|---|---|
| Core | realitycheck-core |
String, number, collection, map, file, URI, CSV, date/time, exception, execution, array, stream, iterable, multiline, enum, UUID, byte[] | None |
| JSON | realitycheck-json |
JSON structural diff, dot-path, array-index navigation | Jackson |
| XML | realitycheck-xml |
XPath assertions, XXE-safe parsing | JDK only |
| YAML | realitycheck-yaml |
YAML dot-path queries | SnakeYAML |
| Snapshot | realitycheck-snapshot |
Golden-file snapshot testing | None |
| JUnit 5 | realitycheck-junit5 |
@WithSoftChecks parameter injection |
JUnit Jupiter API |
| BOM | realitycheck-bom |
Version alignment for multi-module use | — |
Reality Check uses explicit, user-defined assertions instead of reflective object traversal. Custom checks are 3 lines with Java records:
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());
}
}
assertThat(payment, MoneyCheck::new).hasCurrency("USD");See DESIGN_DECISIONS.md for the full rationale.
| Document | Description |
|---|---|
| docs/USAGE.md | Full API reference — all assertion types with examples |
| MIGRATION.md | Step-by-step migration from AssertJ and Google Truth |
| docs/ROADMAP.md | What shipped in v1.0 and what's coming next |
| CHANGELOG.md | Release history |
| DESIGN_DECISIONS.md | Why no reflection, soft assertion design, extension model |
| CONTRIBUTING.md | Development setup, coding standards, PR process |
| Javadoc | Full API reference |
- Java 17+
- JUnit 5 (test scope)
mvn clean verify