Testing Kotlin with Spock Part 1 – Object

The object keyword in Kotlin creates singleton in a very convenient way. It can be used for example as a state of an operation. Spock Framework is one of the most expressive and readable test framework available in the Java ecosystem. Let’s see how Kotlin object can be used in the Spock tests.

What do we want to test?

We have a single method validate in Validator interface which returns validation status: Ok or Error.

sealed class ValidationStatus
object Ok : ValidationStatus()
object Error : ValidationStatus()

interface Validator<T> {
    fun validate(value: T): ValidationStatus


We also provide a simple implementation of this interface:

class AdultValidator : Validator<Int> {
    override fun validate(value: Int) = if (value >= 18) Ok else Error


How to test it with Spock?

First – silly approach

First, let’s write a parameterized test for the validator:

AdultValidator sut = new AdultValidator()

def 'should validate age #age'() {
        sut.validate(age) == result
        age | result
        0   | Error
        17  | Error
        18  | Ok
        19  | Ok


We expect it to pass, but it fails… Error and Ok are classes in the code above.

Second – naive approach

We need instances instead, so we modify the test a little:

def 'should validate age #age'() {
        sut.validate(age) == result
        age | result
        0   | new Error()
        17  | new Error()
        18  | new Ok()
        19  | new Ok()


And again, this one fails as well. Why? It is because Error and Ok classes do not have overridden equals method. But why? We expects Kotlin objects (those created with object keyword, not plain object) to have it implemented correctly. What is more, it works correctly in Kotlin:

fun isOk(status:ValidationStatus) = status == Ok

Third – correct approach

Let’s look into the class file:

$ javap com/github/alien11689/testingkotlinwithspock/Ok.class
Compiled from "Validator.kt"
public final class com.github.alien11689.testingkotlinwithspock.Ok extends com.github.alien11689.testingkotlinwithspock.ValidationStatus {
  public static final com.github.alien11689.testingkotlinwithspock.Ok INSTANCE;
  static {};

If we want to access the real object that Kotlin uses in such comparisson, then we should access the class static property called INSTANCE:

def 'should validate age #age'() {
        sut.validate(age) == result
        age | result
        0   | Error.INSTANCE
        17  | Error.INSTANCE
        18  | Ok.INSTANCE
        19  | Ok.INSTANCE

Now the test passes.

Fourth – alternative approach

We can also check the method result without specific instance of the object class and use instanceof or Class#isAssignableFrom instead.

Show me the code

Code is available here.

One thought on “Testing Kotlin with Spock Part 1 – Object”

  1. Hey Dominik,

    That’s an interesting example. Let me add that for the alternate method the Groovy’s `in` operator can be used. Reads a bit better and does kind of the same.

    `result.class in expected`

    Or even shorter:

    `results in expected`

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.