Hello, I have an issue with Spek. It looks like it...
# spek
w
Hello, I have an issue with Spek. It looks like it does share objects between tests within a file. In Java I was using JUnit and each test recreates everything, so there are no issues with some dirty state from test X leaking to test Y. Am I doing something wrong?
r
witoldsz: can you give an example?
w
OK, let me pick something…
Copy code
object ForexRatesSpec: Spek({
    describe("ForexRates") {

        val mq = FakeMQ3()
        val setup = EnvSetup(mq, Config(…))

        val clock = ClockStub()
        val jooq = setup.jooq
        val txm = setup.ultm.txManager
        val db = MarketHistoryDatabase(jooq)

        beforeGroup {
            mq.connect()
        }

        beforeEachTest {
            txm.tx { jooq.truncate(FX_HISTORY).execute() }
            clock.setTime("2017-06-23T12:04:35.500Z")
        }

        on("first call") {
          …
        }

        on("subsequent calls") {
          …
        }
    }
})
If I move everything into
before…
then I will have much more typing: `val`s become `var`s etc…
r
You could use memoized if you're at Kotlin 1.1
val mq by memoized { FakeMQ3() }
w
But I want the opposite, I need fresh FakeMQ3 on each test
r
by default each test will have a unique instance
val mq by memoized(CachingMode.TEST) { FakeMQ3() }
CachingMode.TEST
is the default value
GROUP
and
SCOPE
are supported as well
w
OK, let me check it
It is working, but looks awkward 😕
r
why does it look awkward?
w
You look at the code and everything not marked as memoized is actually memoized.
The only fresh instances are the ones with
memoized
r
well, true but we really don't have control to
val mq = FakeMQ3()
w
JUnit has it right, it just creates test environment for each test.
r
and every group's (
describe
,
context
, etcc..) lambda is executed once.
w
Looks like a legit reason to switch to JUnit 😕
r
JUnit does it that way, spek does it this way.
w
Thanks for your help, I was wondering if I did not miss some configuration for this.
r
Btw, the old way of doing this was by declaring your state as
var
and setting them up in a
beforeEachTest
.
w
That was on my mind as well. At least it makes thie setup clear as to what happens.
r
problem with it is you need to declare the types as nullable
so when using them you have to call them with
!!
w
ah, true
r
lateinit
is not supported locally
j
@witoldsz don't you end up with the same issue in Junit? you would have to declare
var mq: FakeMQ3? = null
and setup with
@Before
?
w
No, it will recreate the test on each test.
👍 1
Working with it in Java for ages, with Kotlin I wanted to try something new.
Would it be possible to change Spek, so it would not share objects between tests? Maybe with some kind of configuration option, so it would not affect existing users?
r
I don't think so, spek is very different from JUnit. First there is no notion of "spek instances", you can even use
object
to declare a spek. As you can also see, everything is setup-d using lambda blocks, no class instances there only local variables.
Also, say your spek has 100 tests (`it`s declared) if we allow that we have 100 instances of that spec and we have to execute all the lambdas 100 times, since there is no way to know the test tree without executing it.
w
😞