Search code examples
kotlinkotlinx.coroutinesspek

How organize multiple coroutine and expectation blocks in a Kotlin Spek test?


I wrote a failing Spek test because I made an incorrect assumption about execution order involving multiple coroutines and it functions:

given("a test") {
    runBlocking { print("a") }

    it("block 1") {
        runBlocking { print("b") }
    }

    runBlocking { print("c") }

    it("block 2") {
        runBlocking { print("d") }
    }
}

I expected abcd to be printed, but acbd actually printed.

How should I write this test so that it both visually reads and executes in the intended order?


Solution

  • Spek is basically written using lambdas, so in order for Spek to know about the test tree it has to execute it - that's called the discovery phase. In that phase group scopes (given, describe, context) are executed, in your case runBlocking { print("a") } and runBlocking { print("c") } are invoked. Once the test tree is known, Spek can now proceed to the execution phase. In this phase Spek will execute the lambdas passed to test (it) and action (on) scopes.

    As a fix to your problem you should use the action scope on instead of given.

    on("a test") {
        runBlocking { print("a") }
    
        it("block 1") {
            runBlocking { print("b") }
        }
    
        runBlocking { print("c") }
    
        it("block 2") {
            runBlocking { print("d") }
        }
    }