Kotlin `suspend` test should use `runTest`.
Context, this GitHub comment and the ones below it: https://github.com/junit-team/junit-framework/issues/1914#issuecomment-2893644101
Furthermore, if suspend tests use runTest, it would be amazing to support specifying a dispatcher via an annotation:
@TestDispatcher(FooDispatcher::class)
class BarTest {
...
}
I find it weird to need to replace the dispatcher only on a single test instead of the whole class. @TestDispatcher(FooDispatcher::class) should work if it is also annotating a test method for that use case.
Most built-in dispatchers do not exposed as a type:
https://github.com/Kotlin/kotlinx.coroutines/blob/master/kotlinx-coroutines-core/jvm/src/Dispatchers.kt#L14
DefaultScheduler, DefaultIoScheduler, Unconfined - internal objects
Main - property
StandardTestDispatcher, UnconfinedTestDispatcher - functions
So it's not realistic to support FooDispatcher::class, unless it's some factory that returns dispatcher. So then it would be nice to have built-in factory implementations for well-known dispatchers.
More generic feature would be supporting injection arbitrary CoroutineScope, since there is no benefit for tests to inject StandardTestDispatcher but not be able to access TestScope.
And then, if you look at amount of boilerplate that passing TestScope via parameter of context parameter requires, it's less obvious why one will not just write:
@Test
fun testExampleBackgroundJob() = runTest {
...
}
and prefer this:
@Test
suspend fun testExampleBackgroundJob(testScope: TestScope) {
}
// or
@Test
context(testScope: TestScope)
suspend fun testExampleBackgroundJob() {
}
// this is kinda ok, but again just more boilerplate than runTest
@Test
suspend fun TestScope.testExampleBackgroundJob() {
}
I don't know how JUnit works, but just adding the annotation should add the TestScope automatically as some kind of receiver, probably as a context parameter as it is the future of Kotlin, even if the user has not explicitly written it.
I agree. My hack https://gist.github.com/ephemient/01d6e5766e6f8ea02839b4d7c3f94e55 supported test methods receiving TestScope as a receiver or other parameter, and context parameters would make sense too.
And then, if you look at amount of boilerplate that passing TestScope via parameter of context parameter requires, it's less obvious why one will not just write:
@Test fun testExampleBackgroundJob() = runTest { ... }
This already works today, doesn't it? If so, I think we should document is as an alternative to suspend functions (or using runBlocking) directly. If anyone needs a special dispatcher, I think they should set this up themselves in the test method body. WDYT?
@marcphilipp yes, I think using runTest directly make more sense and can be just documented. It's part of kotlinx-coroutines-test and user can use any version, so junit do not need to add it to classpath or require it in runtime.
Not sure about use-case for injecting dispatcher, I don't have any.
If you would like us to be able to process this issue, please provide the requested information. If the information is not provided within the next 3 weeks, we will be unable to proceed and this issue will be closed.
Closing due to lack of requested feedback. If you would like to proceed with your contribution, please provide the requested information and we will re-open this issue.