Skip to content

Commit

Permalink
Fixed use of type alias in shouldBeEqualToComparingFields (#3927)
Browse files Browse the repository at this point in the history
Fixes #3880
  • Loading branch information
sksamuel committed Mar 11, 2024
1 parent b560a8c commit 0660eb3
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import io.kotest.matchers.Matcher
import io.kotest.matchers.MatcherResult
import io.kotest.matchers.should
import io.kotest.matchers.shouldNot
import kotlin.reflect.KClass
import kotlin.reflect.KProperty
import kotlin.reflect.KProperty1
import kotlin.reflect.KVisibility
import kotlin.reflect.full.memberProperties
import kotlin.reflect.jvm.isAccessible
import kotlin.reflect.jvm.jvmName

/**
* Asserts that this is equal to [other] using specific fields
Expand Down Expand Up @@ -581,7 +583,10 @@ internal fun <T> checkEqualityOfFieldsRecursively(
return fields.mapNotNull {
val actual = it.getter.call(value)
val expected = it.getter.call(other)
val typeName = it.returnType.toString().replace("?", "")
val typeName = when (val classifier = it.returnType.classifier) {
is KClass<*> -> classifier.qualifiedName ?: classifier.jvmName
else -> it.returnType.toString().replace("?", "")
}
val heading = "${it.name}:"

if (requiresUseOfDefaultEq(actual, expected, typeName, config.useDefaultShouldBeForFields)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,147 +18,159 @@ import io.kotest.matchers.comparables.shouldBeGreaterThanOrEqualTo
import io.kotest.matchers.comparables.shouldBeLessThan
import io.kotest.matchers.comparables.shouldBeLessThanOrEqualTo
import io.kotest.matchers.comparables.shouldNotBeEqualComparingTo
import io.kotest.matchers.equality.FieldsEqualityCheckConfig
import io.kotest.matchers.equality.shouldBeEqualToComparingFields
import io.kotest.matchers.should
import io.kotest.matchers.shouldBe
import io.kotest.matchers.shouldNot
import io.kotest.property.checkAll

typealias MyMap = Map<String, String>

class ComparableMatchersTest : FreeSpec() {

class ComparableExample(
private val underlying: Int
) : Comparable<ComparableExample> {
override fun compareTo(other: ComparableExample): Int {
return when {
underlying == other.underlying -> 0
underlying > other.underlying -> 1
else -> -1
class ComparableExample(
private val underlying: Int
) : Comparable<ComparableExample> {
override fun compareTo(other: ComparableExample): Int {
return when {
underlying == other.underlying -> 0
underlying > other.underlying -> 1
else -> -1
}
}
}
}

init {

val cn = ComparableExample(-100)
val cz = ComparableExample(0)
val cp = ComparableExample(100)

"Comparable matchers" - {

"beLessThan (`<`) comparison" - {

"should pass test for lesser values" {
arrayOf(cn to cz, cz to cp).forAll {
it.first shouldBe lt(it.second)
it.first should beLessThan(it.second)
it.first shouldBeLessThan it.second
}
}

"should throw exception for equal values" {
arrayOf(cn, cz, cp).forAll {
shouldThrow<AssertionError> { it shouldBe lt(it) }
shouldThrow<AssertionError> { it should beLessThan(it) }
shouldThrow<AssertionError> { it shouldBeLessThan it }
}
}

"should throw exception for greater values" {
arrayOf(cp to cz, cz to cn).forAll {
shouldThrow<AssertionError> { it.first shouldBe lt(it.second) }
shouldThrow<AssertionError> { it.first should beLessThan(it.second) }
shouldThrow<AssertionError> { it.first shouldBeLessThan it.second }
}
}
}

}
init {

"beLessThanOrEqualTo (`<=`) comparison" - {
val cn = ComparableExample(-100)
val cz = ComparableExample(0)
val cp = ComparableExample(100)

"should pass for lesser or equal values" {
arrayOf(cn to cn, cn to cz, cz to cz, cz to cp, cp to cp).forAll {
it.first shouldBe lte(it.second)
it.first should beLessThanOrEqualTo(it.second)
it.first shouldBeLessThanOrEqualTo it.second
}
}
"Comparable matchers" - {

"should throw exception for greater values" {
arrayOf(cp to cz, cz to cn).forAll {
shouldThrow<AssertionError> { it.first shouldBe lte(it.second) }
shouldThrow<AssertionError> { it.first should beLessThanOrEqualTo(it.second) }
shouldThrow<AssertionError> { it.first shouldBeLessThanOrEqualTo it.second }
}
}
"beLessThan (`<`) comparison" - {

}
"should pass test for lesser values" {
arrayOf(cn to cz, cz to cp).forAll {
it.first shouldBe lt(it.second)
it.first should beLessThan(it.second)
it.first shouldBeLessThan it.second
}
}

"beGreaterThan (`>`) comparison" - {

"should pass for greater values" {
arrayOf(cp to cz, cz to cn).forAll {
it.first shouldBe gt(it.second)
it.first should beGreaterThan(it.second)
it.first shouldBeGreaterThan it.second
}
}

"should throw exception for equal values" {
arrayOf(cn, cz, cp).forAll {
shouldThrow<AssertionError> { it shouldBe gt(it) }
shouldThrow<AssertionError> { it should beGreaterThan(it) }
shouldThrow<AssertionError> { it shouldBeGreaterThan it }
}
}

"should throw exception for lesser values" {
arrayOf(cn to cz, cz to cp).forAll {
shouldThrow<AssertionError> { it.first shouldBe gt(it.second) }
shouldThrow<AssertionError> { it.first should beGreaterThan(it.second) }
shouldThrow<AssertionError> { it.first shouldBeGreaterThan it.second }
}
}
"should throw exception for equal values" {
arrayOf(cn, cz, cp).forAll {
shouldThrow<AssertionError> { it shouldBe lt(it) }
shouldThrow<AssertionError> { it should beLessThan(it) }
shouldThrow<AssertionError> { it shouldBeLessThan it }
}
}

}
"should throw exception for greater values" {
arrayOf(cp to cz, cz to cn).forAll {
shouldThrow<AssertionError> { it.first shouldBe lt(it.second) }
shouldThrow<AssertionError> { it.first should beLessThan(it.second) }
shouldThrow<AssertionError> { it.first shouldBeLessThan it.second }
}
}

"beGreaterThanOrEqualTo (`>=`) comparison" - {

"should pass for greater than or equal values" {
arrayOf(cp to cp, cp to cz, cz to cz, cz to cn, cn to cn).forAll {
it.first shouldBe gte(it.second)
it.first should beGreaterThanOrEqualTo(it.second)
it.first shouldBeGreaterThanOrEqualTo it.second
}
}

"should throw exception for lesser values" {
arrayOf(cn to cz, cz to cp).forAll {
shouldThrow<AssertionError> { it.first shouldBe gte(it.second) }
shouldThrow<AssertionError> { it.first should beGreaterThanOrEqualTo(it.second) }
shouldThrow<AssertionError> { it.first shouldBeGreaterThanOrEqualTo it.second }
}
}
}
}

"compareTo" - {
"beLessThanOrEqualTo (`<=`) comparison" - {

"should pass for equal values" {
checkAll { a: Int, b: Int ->
if (a == b) {
a should compareTo(b, Comparator { o1, o2 -> o1 - o2 })
a.shouldBeEqualComparingTo(b, Comparator { o1, o2 -> o1 - o2 } )
a shouldBeEqualComparingTo b
"should pass for lesser or equal values" {
arrayOf(cn to cn, cn to cz, cz to cz, cz to cp, cp to cp).forAll {
it.first shouldBe lte(it.second)
it.first should beLessThanOrEqualTo(it.second)
it.first shouldBeLessThanOrEqualTo it.second
}
}
else {
a shouldNot compareTo(b, Comparator { o1, o2 -> o1 - o2 })
a.shouldNotBeEqualComparingTo(b, Comparator { o1, o2 -> o1 - o2 } )
a shouldNotBeEqualComparingTo b

"should throw exception for greater values" {
arrayOf(cp to cz, cz to cn).forAll {
shouldThrow<AssertionError> { it.first shouldBe lte(it.second) }
shouldThrow<AssertionError> { it.first should beLessThanOrEqualTo(it.second) }
shouldThrow<AssertionError> { it.first shouldBeLessThanOrEqualTo it.second }
}
}

}

"beGreaterThan (`>`) comparison" - {

"should pass for greater values" {
arrayOf(cp to cz, cz to cn).forAll {
it.first shouldBe gt(it.second)
it.first should beGreaterThan(it.second)
it.first shouldBeGreaterThan it.second
}
}
}
}
}
}

}
"should throw exception for equal values" {
arrayOf(cn, cz, cp).forAll {
shouldThrow<AssertionError> { it shouldBe gt(it) }
shouldThrow<AssertionError> { it should beGreaterThan(it) }
shouldThrow<AssertionError> { it shouldBeGreaterThan it }
}
}

"should throw exception for lesser values" {
arrayOf(cn to cz, cz to cp).forAll {
shouldThrow<AssertionError> { it.first shouldBe gt(it.second) }
shouldThrow<AssertionError> { it.first should beGreaterThan(it.second) }
shouldThrow<AssertionError> { it.first shouldBeGreaterThan it.second }
}
}

}

"beGreaterThanOrEqualTo (`>=`) comparison" - {

"should pass for greater than or equal values" {
arrayOf(cp to cp, cp to cz, cz to cz, cz to cn, cn to cn).forAll {
it.first shouldBe gte(it.second)
it.first should beGreaterThanOrEqualTo(it.second)
it.first shouldBeGreaterThanOrEqualTo it.second
}
}

"should throw exception for lesser values" {
arrayOf(cn to cz, cz to cp).forAll {
shouldThrow<AssertionError> { it.first shouldBe gte(it.second) }
shouldThrow<AssertionError> { it.first should beGreaterThanOrEqualTo(it.second) }
shouldThrow<AssertionError> { it.first shouldBeGreaterThanOrEqualTo it.second }
}
}
}

"compareTo" - {

"should pass for equal values" {
checkAll { a: Int, b: Int ->
if (a == b) {
a should compareTo(b, Comparator { o1, o2 -> o1 - o2 })
a.shouldBeEqualComparingTo(b, Comparator { o1, o2 -> o1 - o2 })
a shouldBeEqualComparingTo b
} else {
a shouldNot compareTo(b, Comparator { o1, o2 -> o1 - o2 })
a.shouldNotBeEqualComparingTo(b, Comparator { o1, o2 -> o1 - o2 })
a shouldNotBeEqualComparingTo b
}
}
}

"work for alias to java type" {

data class Widget(val things: MyMap, val ignoreMe: String)

val widget = Widget(mapOf("a" to "b"), ignoreMe = "blah")
widget.shouldBeEqualToComparingFields(
Widget(mapOf("a" to "b"), ignoreMe = "foo"),
FieldsEqualityCheckConfig(propertiesToExclude = listOf(Widget::ignoreMe))
)
}
}
}
}
}

0 comments on commit 0660eb3

Please sign in to comment.