I use tests with mocha and expect that async `@bef...
# javascript
u
I use tests with mocha and expect that async
@beforeTest
and async
@afterTest
will be properly chained. But in fact
@beforeTest
,
@afterTest
and an actual test starts in parallel. How to achieve the expected result?
Copy code
class TestA : CoroutineScope by GlobalScope {

    @BeforeTest
    fun beforeTest() = promise {
        println("beforeTest START")
        delay(100)
        println("beforeTest END")
    }

    @AfterTest
    fun afterTest() = promise {
        println("afterTest START")
        delay(100)
        println("afterTest END")
    }

    @Test
    fun test1() = promise {
        println("test1 START")
        delay(100)
        assertTrue(true)
        println("test1 END")
    }

    @Test
    fun test2() = promise {
        println("test2 START")
        delay(100)
        assertTrue(true)
        println("test2 END")
    }
}
result:
Copy code
JS: beforeTest START
JS: test1 START
JS: afterTest START
JS: beforeTest END
JS: test1 END
JS: afterTest END

JS: beforeTest START
JS: test2 START
JS: afterTest START
JS: beforeTest END
JS: test2 END
JS: afterTest END
u
so, just to be sure I got you right - tests are running in parallel (how exactly this is achieved?) and in that case before/afterTest behave inconsistently - or does it happen in any scenario, no matter parallel or not?
u
@[JB] Shagen No. Tests are chained properly (as you can see in the above log). But before/afterTest run together with actual test and executed "in parallel" with actual test (that not what I expect). I expect:
Copy code
JS: beforeTest START
JS: beforeTest END
JS: test1 START
JS: test1 END
JS: afterTest START
JS: afterTest END

JS: beforeTest START
JS: beforeTest END
JS: test2 START
JS: test2 END
JS: afterTest START
JS: afterTest END
u
I have no clue about js testing. But you might want to remove
promise
from the definitions?
u
@uli as you can see there are
delay(100)
in
promise
block
u
So maybe you want to wait for the promise.
Your initial question was, why do this run in parallel. The answer is, because you tell them to do so. BeforeTest is finished, as soon as the promise is spawned.
u
@uli yes, I want to wait for the promise. That's how actual tests works in the above code. They are run one by one. My question is not "why do this run in parallel?"
u
Well all three method start sequentially. But they finish as soon as they have spawned their promises. So you need to await the promises
You could try runBlockingTest instead of promise
If this is available in JS
u
@uli there are no
runBlocking
in kotlin/js
u
@uli
kotlinx-coroutines-test
is experimental. Looks like it was released in
1.3.0-M1
4 day ago. I will try, thank you.
@[JB] Shagen is
kotlinx-coroutines-test
available for kotlin/js (I specify it in dependencies, but can't access it)? Or can it be resolved without
kotlinx-coroutines-test
?
u
Not sure if it is available. You could also try wrapping your call into coroutineScope or CoroutineScope instead of runBlocking. I don't remember which one and I am on mobile right now
a
Still experiencing this. Any solutions or work arounds?
r
I just ran through my source and realized I never actually use the Before or After annotations, so I never had to solve this problem for myself. I’m guessing the js implementation of those doesn’t actually pass the promise all the way through to the framework, which leaves you with no options for using them. 😞 I have a vague memory of looking this up in the source code at one point? That would have been over a year ago I think. The pattern I follow, which would qualify as a work-around I suppose, is… call a function at the beginning of your async test that acts as your “before” function.
a
I guess that would work now
j
I searched this Slack for the exact same problem.
kotlinx-coroutines-test
is still a JVM-only library, I have asked a while ago if JetBrains could release a multiplatform version of it, it's got some traction now, but still not done: https://github.com/Kotlin/kotlinx.coroutines/issues/1996 It should come in 1.6. In the meantime, using promises to run async test doesn't seem to work properly as mentioned above. My current workaround is to put the cleanup in a
finally
block inside the promise of the test methods instead of in an
@AfterTest
method.