Last active
February 4, 2022 17:34
-
-
Save efenderbosch/f502c1518f6a2c1b636273633ef3ad2f to your computer and use it in GitHub Desktop.
Fluent equal to ignoring for Strikt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package util | |
| import org.junit.jupiter.api.Test | |
| import strikt.api.Assertion | |
| import strikt.api.expectThat | |
| import strikt.assertions.contentEquals | |
| import strikt.assertions.isEqualTo | |
| import java.beans.Introspector | |
| import java.util.* | |
| import kotlin.reflect.KProperty1 | |
| typealias IgnoringBuilder<T> = Assertion.Builder<Pair<T, List<KProperty1<T, Any>>>> | |
| fun <T> Assertion.Builder<T>.ignoring(vararg properties: KProperty1<T, Any>): IgnoringBuilder<T> = | |
| get { subject to properties.toList() } | |
| fun <T : Any> IgnoringBuilder<T>.isEqualTo(expected: T): IgnoringBuilder<T> = | |
| compose(description(), expected) { subject -> | |
| Introspector.getBeanInfo(subject.first::class.java).let { beanInfo -> | |
| beanInfo | |
| .propertyDescriptors | |
| .filter { it.name != "class" && it.name !in subject.second.map { prop -> prop.name } } | |
| .forEach { property -> | |
| val mappedAssertion = get("value of property ${property.name}") { | |
| property.readMethod(first) | |
| } | |
| val otherValue = property.readMethod(expected) | |
| @Suppress("UNCHECKED_CAST") | |
| when { | |
| property.propertyType == BooleanArray::class.java -> | |
| (mappedAssertion as Assertion.Builder<BooleanArray>).contentEquals(otherValue as BooleanArray) | |
| property.propertyType == ByteArray::class.java -> | |
| (mappedAssertion as Assertion.Builder<ByteArray>).contentEquals(otherValue as ByteArray) | |
| property.propertyType == ShortArray::class.java -> | |
| (mappedAssertion as Assertion.Builder<ShortArray>).contentEquals(otherValue as ShortArray) | |
| property.propertyType == IntArray::class.java -> | |
| (mappedAssertion as Assertion.Builder<IntArray>).contentEquals(otherValue as IntArray) | |
| property.propertyType == LongArray::class.java -> | |
| (mappedAssertion as Assertion.Builder<LongArray>).contentEquals(otherValue as LongArray) | |
| property.propertyType == FloatArray::class.java -> | |
| (mappedAssertion as Assertion.Builder<FloatArray>).contentEquals(otherValue as FloatArray) | |
| property.propertyType == DoubleArray::class.java -> | |
| (mappedAssertion as Assertion.Builder<DoubleArray>).contentEquals(otherValue as DoubleArray) | |
| property.propertyType.isArray -> | |
| (mappedAssertion as Assertion.Builder<Array<*>>).contentEquals(otherValue as Array<*>) | |
| else -> mappedAssertion.isEqualTo(otherValue) | |
| } | |
| } | |
| } | |
| } then { | |
| if (allPassed) pass() else fail() | |
| } | |
| fun <T : Any> IgnoringBuilder<T>.unwrap(): Assertion.Builder<T> = get { first } | |
| private fun <T> IgnoringBuilder<T>.description() = | |
| "is equal field-by-field ignoring ${subject.second.joinToString(",", "[", "]") { it.name }} to %s" | |
| class IgnoringBuilderTests { | |
| @Test | |
| fun test() { | |
| val foo1 = Foo("qux", UUID.randomUUID()) | |
| val foo2 = Foo("qux", UUID.randomUUID()) | |
| expectThat(foo1).ignoring(Foo::baz).isEqualTo(foo2).unwrap().and { | |
| // continue using foo1... | |
| } | |
| } | |
| } | |
| data class Foo(val bar: String, val baz: UUID) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You could always structure the assertion as
expectThat(foo1) { ignoring(Foo::baz).isEqualTo(foo2) // continue using foo1... }