-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Possibility to replace default dispatchers #810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'm currently doing this by creating proxy /**
* Collection of Coroutine dispatchers that can be overriden for Unit tests.
**/
object TestableDispatchers {
/**
* [Dispatchers.Default] dispatcher that can be overriden by unit tests.
*/
@JvmStatic
val Default
get() = dispatcherOverride {
Dispatchers.Default
}
/**
* [Dispatchers.Main] dispatcher that can be overriden by unit tests.
*/
@JvmStatic
val Main
get() = dispatcherOverride {
Dispatchers.Main
}
/**
* [Dispatchers.IO] dispatcher that can be overriden by unit tests.
*/
@JvmStatic
val IO
get() = dispatcherOverride {
Dispatchers.IO
}
@JvmStatic
var dispatcherOverride: (() -> CoroutineContext) -> CoroutineContext = { it() }
} Then for tests I just use this JUnit rule to override them: class ImmediateDispatcherRule : TestWatcher() {
// UNCONFINED is experimental, but it is still fine to use it with tests
@Suppress("EXPERIMENTAL_API_USAGE")
override fun starting(description: Description?) {
super.starting(description)
TestableDispatchers.dispatcherOverride = { Dispatchers.Unconfined }
}
override fun finished(description: Description?) {
super.finished(description)
TestableDispatchers.dispatcherOverride = { it() }
}
} Of course this requires additional care when launching coroutines (you cannot just rely on |
I am not in favor of |
Maybe good solution would be to include IntelliJ warning/inspection to not override dispatchers in production code? |
Let me clarify: we are not going to implement it in the form of global settable dispatchers like If you want to have control over dispatchers, use dependency injection and inversion of control.
Inspections and warnings won't help here, because people will use it anyway ("I get used to it in RxJava, so I can ignore this warning"). |
However, we understand that ability to replace dispatchers is very useful during testing and we don't want our users to write additional boilerplate only for tests. We will provide a separate test module (#749) that will allow redefining E.g.
For that purpose, it is probably better to provide something like
|
Sounds good. In most cases in Android result is delivered to the main thread anyway. |
Another use case for this is ability to replace dispatchers with |
Side effects is another case that needs some help for testing. For instance, you can write espresso tests that look like:
And if you've registered your task runners to Espresso as Idling resources, it knows how to await for them to go idle. some code may need to do it explicitly as well:
It would be good to have support for these as well. |
It should be possible to use a custom MainCoroutineDispatcher (with whatever mechanism). There is not only Android and Swing as UI frameworks on the JVM. I develop a SWT application that uses Kotlin coroutines. |
I'm not sure if this commit closes this issue entirely. This issue is about replacing all the dispatchers, while commit only provides replacer for Main dispatchers. From what I can see there is still no good way to inject |
So we should expose the scope of our classes in order to test it? I have no other reason to expose scope and make it public. |
Is there any update on this issue ? I think it would be very helpful for testing to have a way of overriding the other Dispatchers. For example, I want to test this method in my ViewModel :
login() returns Unit and I want to keep it that way. Now I can't test it because I can't find a way of making the test method waiting for what's inside launch() to finish. |
@CharlyLafon37 we are looking at ways to make it working without having to replace dispatchers. A solution that you can use now to make your code testable is to inject the dispatchers into your models. |
@elizarov Too bad. I don't really like the workaround that you suggest as it adds dependencies to the code just for testing purposes. I hope the Kotlin team will build a real solution to this problem (which I think is critical) very soon 😄. |
The dependencies were always there. You're just currently electing to use global static to resolve them. |
I meant one dependency to inject. |
Problem is that this solution only works for the code I can directly edit. If a library that I use has hardcoded |
We'll be working on making such libraries testable. I've created a separate issue #1365 |
So Rx java has a way to inject scheduler (RxJavaPlugins), is there a plan to have a similar thing for coroutines dispatchers?
@gildor
Christoph Sturm (from slack)
The text was updated successfully, but these errors were encountered: