Groups execution order is wrong in Kotlin Spek

664 views Asked by At

Here is my test:

object MySpek : Spek({
    val myMock1: MyMock1 = mock()
    val myMock2: MyMock2 = mock()
    val handler = StartModeHandler(myMock1, myMock2)

    val session = mock<Session> {
        on { user }.doReturn(User.builder().withUserId("userId").build())
    }
    describe("item exists for user") {
        beforeGroup {
            reset(digitalPointDao, trackDao)
        }
    whenever(myMock1.loadItem(session.user.userId)).thenReturn(Optional.of(MyItem()))
        whenever(myMock2.loadSomething()).thenReturn(ArrayList())
        context("method onLaunch was called") {
            val response = handler.onLaunch(session)
            it("should return the response for existing user") {
                //some asserts here
            }
            it("should save the item") {
                //some mock verifies here
            }
        }
    }
})

According to Spek documentation, I expect the flow to be the following:

  1. initialize everything before describe
  2. call beforeGroup
  3. initalize describe body e.g. my whenever calls for mocks
  4. run context
  5. run each it method

But i'm getting the following flow:

  1. initialize everything before describe
  2. run my describe body e.g. my whenever calls for mocks
  3. run context
  4. run beforeGroup
  5. run each it method

Am I miss something and doing something wrong here?

1

There are 1 answers

0
raniejade On BEST ANSWER

As mentioned in the Spek documentation group scopes (given, describe, context) will eagerly execute any code within. Any test state initialization should be done within fixtures (beforeEachTest, beforeGroup, etc ...). You can also use memoized to create a dependency tied to Spek's lifecycle.

object MySpek: Spek({
    val myMock1 by memoized { mock<myMock1>() }
    val myMock2 by memoized { mock<myMock2>() }

    val handler by memoized { StartModeHandler(myMock1, myMock2) }

    val session by memoized { 
        mock<Session> {
            on { user }.doReturn(User.builder().withUserId("userId").build())
        }
    }

    describe("item exists for user") {
        beforeEachTest {
            reset(digitalPointDao, trackDao)
            whenever(myMock1.loadItem(session.user.userId)).thenReturn(Optional.of(MyItem()))
            whenever(myMock2.loadSomething()).thenReturn(ArrayList())
        }

        // use on instead of context
        on("method onLaunch was called") {
            val response = handler.onLaunch(session)
            it("should return the response for existing user") {
                //some asserts here
            }
            it("should save the item") {
                //some mock verifies here
            }
        }

    }
})