A powerful fluent API
Type-safe fluent assertions
val subject = "The Enlightened take things Lightly"
expectThat(subject)
.hasLength(35)
.matches(Regex("[\\w\\s]+"))
.startsWith("T")
Collection handling
Flexible assertions about collections
val subject = listOf("Eris", "Thor", "Anubis", "Ra")
expectThat(subject)
.contains("Eris", "Thor", "Anubis")
“Narrow” the assertion to elements or ranges
expectThat(subject)[0].isEqualTo("Eris")
Make grouping assertions
val subject = Deity.values().map { it.toString() }
expectThat(subject)
.isNotEmpty()
.any { startsWith("E") }
“Soft” assertions
Use lambdas to execute multiple assertions on a subject at once…
val subject = "The Enlightened take things Lightly"
expectThat(subject) {
hasLength(5) // fails
matches(Regex("\\d+")) // fails
startsWith("T") // still evaluated and passes
}
…with structured diagnostics of those that fail
▼ Expect that "The Enlightened take things Lightly":
✗ has length 5
found 35
✗ matches the regular expression /\d+/
found "The Enlightened take things Lightly"
✓ starts with "T"
Use lambdas to execute assertions on multiple subjects at once…
val person1 = Person(name = "David")
val person2 = Person(name = "Ziggy")
expect {
that(person1.name).isEqualTo("David")
that(person2.name).isEqualTo("Ziggy")
}
Strong typing
Assertion functions can "narrow" the type of the assertion
val subject: Any? = "The Enlightened take things Lightly"
expectThat(subject) // type: Assertion.Builder<Any?>
.isNotNull() // type: Assertion.Builder<Any>
.isA<String>() // type: Assertion.Builder<String>
// only available on Assertion.Builder<CharSequence>
.matches(Regex("[\\w\\s]+"))
Assertions can "map" to properties and method results in a type safe way:
val subject = Pantheon.NORSE
expectThat(subject)
.get(Pantheon::ruler) // reference to a property
.get { toString() } // return type of a method call
.isEqualTo("Odin")
Extensibility
Custom assertions are extension functions
fun Assertion.Builder<LocalDate>.isStTibsDay() =
assert("is St. Tib's Day") {
when (MonthDay.from(it)) {
MonthDay.of(2, 29) -> pass()
else -> fail()
}
}
expectThat(LocalDate.of(2020, 2, 29)).isStTibsDay()
Custom mappings are extension properties
val Assertion.Builder<Pantheon>.realm: Assertion.Builder<String>
get() = get { "$ruler to $underworldRuler" }
val subject = Pantheon.NORSE
expectThat(subject)
.realm
.isEqualTo("Odin to Hel")