https://kotlinlang.org logo
#getting-started
Title
# getting-started
h

huehnerlady

10/20/2020, 9:53 AM
I am currently migrating some groovy tests to kotlin. With that I want to write a kotlin (extension?) function to set an immutable property by name with a given value in my constructor. So I have a variable which includes a property name and a variable which includes so if you have a data class:
Copy code
data class Foo(val id: Int? = null, val someStringProperty: String? = null)
I would like to write something like
Copy code
createFoo(propertyName: String, propertyValue: Any): Foo
which I can then use like:
Copy code
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 😉 )
☑️ 1
v

Vampire

10/20/2020, 9:56 AM
If you want people to use Kotlin to write tests, the best way would be to make it somehow possible to write Spock tests in Kotlin. 😄
h

huehnerlady

10/20/2020, 9:56 AM
well with kotest we do have a good alternative I think, it is more about the flexibility to test single fields of a data class now 🙂
d

diesieben07

10/20/2020, 9:57 AM
You will need
kotlin-reflect
, but then you can use:
Copy code
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
        )
    )
}
But I don't know why you would want the type-unsafe version
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.
☝️ 1
h

huehnerlady

10/20/2020, 10:14 AM
The propblem is, I want a test like this:
Copy code
listOf(
          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 🙂
v

Vampire

10/20/2020, 10:19 AM
From a very quick look I wouldn't agree that kotest is anything near a good replacement for Spock. I see no integrated mocking and stubbing, and as far as I have seen you don't get the amazing assertion output that you get with Spock. To just name three of the most prominent points.
But that's just my PoV of course
h

huehnerlady

10/20/2020, 10:52 AM
From my point of view, it is not AS GOOD AS spock, but I have the bit positive of using kotlin and for me/us it is a good enough alternative. I do find that with the kotest together with mockk you have a very nice set of assertions and the mocking also works well. I mean yes mockk is not integrated in kotest, but they do work well together in my opinion. But I guess people have different likes and dislikes so one person might think so and others different. All in all I can say that I started using JUnit 5 and I missed Spock like maaaad. But then I read about kotest and since then I do not miss it as much anymore. 🙂
s

sam

10/20/2020, 11:12 AM
I'm not sure that integrating a mocking libraries with a test framework is better than just using one of the several excellent choices of mocking libraries already available for Kotlin. The one killer feature of Spock that Kotest doesn't have is the power assert output. Other than that, I genuinely don't know why some people say Spock is better than Kotest.
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.
h

huehnerlady

10/20/2020, 11:28 AM
I do not really understand what you mean by that. with kotest you doget that too I thought? What is missing here for you?
Copy code
it("fail id"){
        Foo(1, "foo1") shouldBe Foo(2, "foo1")
      }

---

  it("fail name"){
        Foo(1, "foo1") shouldBe Foo(1, "foo2")
      }
Result
Copy code
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
v

Vampire

10/20/2020, 11:31 AM
Does it properly and nicely work for more complex expressions and things besides data classes like Spock does it? Spock shows you at each "dot" or operator in the expression what the state is and what does or does not match.
s

sam

10/20/2020, 11:33 AM
No that's not present in Kotest, which is the killer feature I mentioned was missing. @huehnerlady the power assertion feature of groovy is very very nice. It shows you the value at each level of an expression. So for
assert(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.
v

Vampire

10/20/2020, 11:34 AM
"of Spock" 😉
s

sam

10/20/2020, 11:35 AM
I thought it was spock too, but it seems to be a groovy thing? http://www.groovy-lang.org/testing.html#_power_assertions
v

Vampire

10/20/2020, 11:35 AM
They copied it partly from Spock, but that's not what you get when using Spock
s

sam

10/20/2020, 11:35 AM
Ah ok
v

Vampire

10/20/2020, 11:35 AM
When using Spock, it's done by Spock
s

sam

10/20/2020, 11:36 AM
Got it
Someone has made it work in kotlin too https://github.com/bnorm/kotlin-power-assert
1
v

Vampire

10/20/2020, 11:36 AM
Disclaimer: In the meantime I became part of the Spock team 😄
s

sam

10/20/2020, 11:36 AM
Disclaimer: I'm part of the Kotest team 😂
v

Vampire

10/20/2020, 11:52 AM
That was obvious 😄
s

sam

10/20/2020, 11:54 AM
haha 🙂
h

huehnerlady

10/20/2020, 12:16 PM
nice for you to find each other, maybe you should have a chat? 😉 I do love spock and I agree that feature is great, to me it is essential to know what is wrong, I did not have any use cases yet where I was hoping for some more detailed information with the ‘common’ matchers. What I miss from spock is that you have a nice given/when/then/where structure, which unfortunately you have in kotest only with a very verbose set of functions (BehaviourSpec), but we found a spec that works for us alright and for the rest we miss I would start putting up issues as I find if you have a problem, ask for it, maybe contribute if you have time, but make yourself known. Having said that… IF spock would work for kotlin as well - AND with the same set of functionality as it does in groovy - I think I would be one of the first people to switch back (sorry @sam 🙈 )
s

sam

10/20/2020, 12:17 PM
lol that's ok, maybe I should use spock as well 😛
v

Vampire

10/20/2020, 12:18 PM
@huehnerlady "for kotlin" like writing in kotlin or testing kotlin code?
h

huehnerlady

10/20/2020, 12:18 PM
well the way kotest is developing I could imagine it could be a very good alternative to spock in future. So far it is a good-enough-for-me alternative 🙂
@Vampire like writing kotlin 🙂 We already use it in a different project to test kotlin code, but I prefer to use the same language for test and prod code
v

Vampire

10/21/2020, 2:09 PM
Yes, that would be amazing. But probably not happening unless someone very savvy in Kotlin Compiler Plugins and Groovy AST Transformations steps up to give it a shot. I'd also like being able to write Spock specs in Kotlin. Unfortunately I fear some things cannot work like omitting the data variables in the parameter list as then probably the compiler complains, unless the compiler plugin gets a chance to fix this up before the compiler complains.
h

huehnerlady

10/21/2020, 2:41 PM
I can understand that, what a shame. But hopefully kotest continues to blume 🙂