huehnerlady
10/20/2020, 9:53 AMdata class Foo(val id: Int? = null, val someStringProperty: String? = null)
I would like to write something like
createFoo(propertyName: String, propertyValue: Any): Foo
which I can then use like:
val foo1 = createFoo("id", 5) // Foo(id = 5, someStringProperty = null)
val foo2 = createFoo("someStringProperty", "someString") // Foo(id = null, someStringProperty= "someString")
Any idea how I can achieve that?
It might look very hacky… but it would be really useful for the tests we have (and to convinde colleagues who love grrovy a bit more 😉 )Vampire
10/20/2020, 9:56 AMhuehnerlady
10/20/2020, 9:56 AMdiesieben07
10/20/2020, 9:57 AMkotlin-reflect
, but then you can use:
fun createFoo(propertyName: String, propertyValue: Any?): Foo {
val primaryConstructor = Foo::class.primaryConstructor ?: error("Missing constructor")
return primaryConstructor.callBy(
mapOf(
primaryConstructor.parameters.single { it.name == propertyName } to propertyValue
)
)
}
createFoo("id", 5)
when you can have the type-checked and safe version Foo(id=5)
, which is shorter and much more clear in what it does.huehnerlady
10/20/2020, 10:14 AMlistOf(
row("id", 5),
row("someStringProperty", "someStringProperty")
).map { (field: String, value: Any) ->
it("test $field=$value"){
val testdata = createFoo(field, value)
do something with it
}
So I basically want to automate tests without having to dulpicate anything. Would never think about it for production code of course, but for tests we do this regularly and it does make the tests very easy to read. and in groovy it is very easy as we mostly use Maps there. and I made the suggestion to move from spock/groovy tests to kotest/kotlin so I feel in the need of finding solutions that do not blow up the tests too much as they are already much different to spock 😉
Thanks for your help, this works like a charm 🙂Vampire
10/20/2020, 10:19 AMhuehnerlady
10/20/2020, 10:52 AMsam
10/20/2020, 11:12 AMhuehnerlady
10/20/2020, 11:28 AMit("fail id"){
Foo(1, "foo1") shouldBe Foo(2, "foo1")
}
---
it("fail name"){
Foo(1, "foo1") shouldBe Foo(1, "foo2")
}
Result
data class diff for Foo
Expected :Foo(id=2, name=foo1)
Actual :Foo(id=1, name=foo1)
<Click to see difference>
org.opentest4j.AssertionFailedError: data class diff for Foo
└ id: expected:<2> but was:<1>
---
data class diff for Foo
Expected :Foo(id=1, name=foo2)
Actual :Foo(id=1, name=foo1)
<Click to see difference>
org.opentest4j.AssertionFailedError: data class diff for Foo
└ name: expected:<"foo2"> but was:<"foo1">
That’s not to say Spock isn’t better of course, just that I’m not aware of the missing features. I’d love people to open tickets at kotest.io so they could be added.But why don’t you open ttickets if you feel something is missing? I did that too and so far had very good experience with it. Also the #kotest channel is always helpful if you have a question
Vampire
10/20/2020, 11:31 AMsam
10/20/2020, 11:33 AMassert(x.y.z == a)
it will show you what x is, what y is on x, and what z is on y, so you can see where your expectation diverged.Vampire
10/20/2020, 11:34 AMsam
10/20/2020, 11:35 AMVampire
10/20/2020, 11:35 AMsam
10/20/2020, 11:35 AMVampire
10/20/2020, 11:35 AMsam
10/20/2020, 11:36 AMVampire
10/20/2020, 11:36 AMsam
10/20/2020, 11:36 AMVampire
10/20/2020, 11:52 AMsam
10/20/2020, 11:54 AMhuehnerlady
10/20/2020, 12:16 PMsam
10/20/2020, 12:17 PMVampire
10/20/2020, 12:18 PMhuehnerlady
10/20/2020, 12:18 PMVampire
10/21/2020, 2:09 PMhuehnerlady
10/21/2020, 2:41 PM