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() } }