1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package social.grain.support
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.resetMain
import kotlinx.coroutines.test.setMain
import org.junit.rules.TestWatcher
import org.junit.runner.Description
/**
* Runs `viewModelScope` work off the test thread.
*
* Robolectric runs the test body *on* the main thread, so a view model's
* coroutines and the assertions waiting on them would be the same thread — and
* anything that blocks waiting for state would deadlock against the work that
* produces it. `Unconfined` sidesteps that without a virtual clock: each
* coroutine simply carries on wherever its last suspension resumed it, which
* for these view models is the IO thread the request came back on.
*
* That leaves the tests waiting in real time, which is the point — the stub
* server answers through OkHttp's own dispatcher, and no test scheduler
* controls that.
*/
@OptIn(ExperimentalCoroutinesApi::class)
class MainDispatcherRule : TestWatcher() {
override fun starting(description: Description) {
Dispatchers.setMain(Dispatchers.Unconfined)
}
override fun finished(description: Description) {
Dispatchers.resetMain()
}
}