We're using JUnit and doing the pattern where we w...
# coroutines
d
We're using JUnit and doing the pattern where we write lots of tests like
@Test fun foo = runBlocking {
. (We haven't tried using
runBlockingTest
since we haven't needed the extra time-related power it brings — but maybe this is the answer to our issue?) A problem we've been running into is that it's quite easy to have a test whose final line doesn't return Unit. Then the runBlocking doesn't return Unit and neither does the test function, and JUnit just skips it. There is an IntelliJ inspection for this at least but it seems like a bit of a pain. What do people do for this?
@Test fun foo: Unit = runBlocking {
?
@Test fun foo() { runBlocking {
? Something else?
Actually it's worse than that: IntelliJ suggests the
: Unit
answer but that doesn't actually compile.
runBlocking<Unit>
works but isn't what IntelliJ says!
s
Probably not what you’re looking for, sorry, but I use KotlinTest which has direct support for running suspend functions in their test cases. I original stared using KotlinTest for it’s feature set in comparison to JUnit tho.
d
Yeah, we are currently porting a codebase from "not coroutines" to "coroutines" (and from ratpack to ktor) and also porting all tests to a new library seems like a bit much 🙂
s
Other than that
runBlocking<Unit>
is my way to go if I run into that scenario.
That is definitely fair! 😄
d
My question might really be "is there any downside to using
runBlockingTest
in my JUnit tests if I'm not using any of its fancy features?"
s
This is similar to runBlocking but it will immediately progress past delays and into launch and async blocks.
d
Yeah, but I'm trying to understand if that's ever a bad thing for my tests.
t
In fact,
runBlockingTest
provides much more than just fast-forwarding delays and
Unit
return type: - it fails the test if a coroutine is still active for some time after the test block ends, - it reports uncaught exceptions as test failures.
d
Hmm. Is it wrong to use runBlockingTest with code that does (suspending) IO? Switched some runBlockings over to runBlockingTest and I'm now getting stuff like:
Copy code
java.lang.IllegalStateException: This job has not completed yet

	at kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull(JobSupport.kt:1128)
	at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:53)
ie, is runBlockingTest really only designed for code that has delay and timeouts, not arbitrary async IO? Or maybe the problem is that the code under rest runs some code in a non default dispatcher?
t
Never noticed such behavior before. Just reproduced it with those simple lines of code :
Copy code
fun main() = runBlockingTest {
    println("Start")
    withContext(<http://Dispatchers.IO|Dispatchers.IO>) {}
    println("End")
}
The funny part is that I get the following :
Copy code
Start
Exception in thread "main" java.lang.IllegalStateException: This job has not completed yet
	at kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull(JobSupport.kt:1128)
	at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:53)
	at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest$default(TestBuilders.kt:45)
	at fr.nihilus.music.media.CoroutinesPlaygroundKt.main(CoroutinesPlayground.kt:23)
	at fr.nihilus.music.media.CoroutinesPlaygroundKt.main(CoroutinesPlayground.kt)
End
I don't think that's the intented behavior ...
@David Glasser, take a look at this issue : https://github.com/Kotlin/kotlinx.coroutines/issues/1365
s
Btw @David Glasser if you use AnnotationSpec in KotlinTest, you should be able to migrate your tests by just changing some imports.
d
Does KotlinTest work with all the other tools that know about junit? Display in IntelliJ, click to run just one test function, etc?
s
There's an intellij plugin to run a single test. You can run the entire class without the plugin.
It's built on top of JUnit Platform, which is the same underlying framework that JUnit 5 uses. JUnit platform and JUnit 5 are actually quite separate things. So yes, it should work with everything that is JUnit compatible.