Nino
04/18/2025, 12:24 PMlabel
and other stuff has great value to test.
I would like to avoid overriding the equal function of the data class for obvious reasons.
Any ideas ?
// Source code
data class Foo(
val label: String,
val onClicked: () -> Unit,
val onValueChanged: (Int) -> Unit,
)
object FooMapper {
fun map(
label: String,
viewModel: FooViewModel,
) = Foo(
label = label,
onClicked = { viewModel.onFooClicked() },
onValueChanged = { viewModel.onValueChanged(it.toLong()) },
)
}
class FooViewModel {
fun onFooClicked() { /* whatever */ }
fun onValueChanged(value: Long) { /* whatever */ }
}
// Unit tests
class FooMapperTest {
@Test
fun `foo map`() {
// Given
val label = "label"
val fooViewModel = mockk<FooViewModel>()
// When
val result = FooMapper.map(label = label, viewModel = fooViewModel)
// Then
// !! What should I use there?
assertEquals(
Foo(label = label, onClicked = {}, onValueChanged = {}),
result
)
}
}
Nino
04/18/2025, 12:28 PMobject FooMapper {
fun map(label: String, viewModel: FooViewModel) = Foo(
label = label,
onClicked = viewModel::onFooClicked,
onValueChanged = { viewModel.onValueChanged(it.toLong()) },
)
}
assertEquals(
Foo(label = label, onClicked = fooViewModel::onFooClicked, onValueChanged = {}),
result
)
But sometime some kind of mapping will happen in the UI and it should stay there, so the signature between the UiState and the Viewmodel are not the same (like in onValueChanged
, which is an Int for example in the ui), and it doesn't work anymore since I need an "intermediate" lambda to do the mappingephemient
04/18/2025, 3:05 PMinfix fun Any?.reflectiveEquals(other: Any?): Boolean = when {
this == null -> other == null
other == null -> false
else -> this::class == other::class && this::class.memberProperties.all { kproperty ->
val a = (kproperty as KProperty1<Any, Any?>)(this)
val b = kproperty(other)
val classifier = kproperty.returnType.classifier
when {
classifier !is KClass<*> -> a == b
classifier.isFun || classifier.isSubclassOf(Function::class) -> (a != null) == (b != null)
classifier.isData -> a reflectiveEquals b
else -> a == b
}
}
}
ephemient
04/18/2025, 3:06 PMfun Foo.testEquals(other: Foo): Boolean
extension for every
@GenerateTestEquals
data class Foo(...)
Nino
04/18/2025, 3:58 PMephemient
04/18/2025, 4:04 PMephemient
04/18/2025, 4:06 PMephemient
04/18/2025, 4:06 PMephemient
04/18/2025, 4:07 PMephemient
04/18/2025, 4:13 PM@Serializable
class, tries to reflectively instantiate it (including instantiating parameters), and polymorphically serializes every one with every superclass to check that it worksephemient
04/18/2025, 4:15 PMephemient
04/18/2025, 4:15 PMephemient
04/18/2025, 4:17 PM