Search code examples
kotlinintellij-ideakotest

"the expression is unused" when using kotest in intellij


With this kotlin test written with Kotest, IntelliJ shows the warning "The expression is unused" and syntax coloration is not working. Also, when running the tests, the test is not found.

class TalentMatchServiceSpec : StringSpec() {

    init {


        "add 3 to 2 should give 5"
        {
            // Given integers 2 and 3
            val two = 2
            val three = 3

            // When adding both numbers
            val sum = two + three

            // Then the result is 5
            sum shouldBe 5
        }

    }
}

Solution

  • @Thomas Martin's answer is correct, but you asked why it makes a difference.

    The SpringSpec in Kotest relies on some Kotlin DSL features to work. Let's demonstrate by building the same function from scratch.

    We would start by using Kotlin's extension functions. This allows us to add functions to classes we don't control.

    So,

    fun String.test(test: () -> Unit)
    

    So then we can call this test function on any string:

    "this is a test".test({ 1 + 2 shouldBe 3 })
    

    Secondly, Kotlin allows any final lambda arg to be brought outside of the parens. So foo(arg, arg2, arg3, lambda) can become foo(arg, arg2, arg3) lambda. This means we can write our test as:

    "this is a test".test { 1 + 2 shouldBe 3 } 
    

    Next, we can mark functions as infix and then we do not need to use the dot to invoke them. So our test function becomes:

    infix fun String.test(test: () -> Unit)
    

    And our test now looks like:

    "this is a test" test { 1 + 2 shouldBe 3 } 
    

    Finally, any function named invoke and marked as an operator function can be invoked without the function name. So operator fun invoke(a: String, b: String) inside a class Foo can be invoked as both the regular Foo.invoke(a,b) or just Foo(a, b).

    So putting all this together, our final test function looks like:

    operator fun String.invoke(test: () -> Unit)
    

    And our test ends up as:

    "this is a test" { 1 + 2 shouldBe 3 }
    

    Or more likely,

    "this is a test" { 
      1 + 2 shouldBe 3 
    } 
    

    If the braces are moved to the next line, as in your original question, it just looks like a String followed by an unrelated lambda block. Two different expressions.