1 package kotlinx.coroutines.test 2 3 import kotlinx.coroutines.testing.* 4 import kotlinx.coroutines.* 5 import kotlinx.coroutines.test.internal.* 6 import kotlin.coroutines.* 7 import kotlin.test.* 8 9 class TestDispatchersTest: OrderedExecutionTestBase() { 10 11 @BeforeTest setUpnull12 fun setUp() { 13 Dispatchers.setMain(StandardTestDispatcher()) 14 } 15 16 @AfterTest tearDownnull17 fun tearDown() { 18 Dispatchers.resetMain() 19 } 20 21 /** Tests that asynchronous execution of tests does not happen concurrently with [AfterTest]. */ 22 @Test <lambda>null23 fun testMainMocking() = runTest { 24 val mainAtStart = TestMainDispatcher.currentTestDispatcher 25 assertNotNull(mainAtStart) 26 withContext(Dispatchers.Main) { 27 delay(10) 28 } 29 withContext(Dispatchers.Default) { 30 delay(10) 31 } 32 withContext(Dispatchers.Main) { 33 delay(10) 34 } 35 assertSame(mainAtStart, TestMainDispatcher.currentTestDispatcher) 36 } 37 38 /** Tests that the mocked [Dispatchers.Main] correctly forwards [Delay] methods. */ 39 @Test <lambda>null40 fun testMockedMainImplementsDelay() = runTest { 41 val main = Dispatchers.Main 42 withContext(main) { 43 delay(10) 44 } 45 withContext(Dispatchers.Default) { 46 delay(10) 47 } 48 withContext(main) { 49 delay(10) 50 } 51 } 52 53 /** Tests that [Distpachers.setMain] fails when called with [Dispatchers.Main]. */ 54 @Test testSelfSetnull55 fun testSelfSet() { 56 assertFailsWith<IllegalArgumentException> { Dispatchers.setMain(Dispatchers.Main) } 57 } 58 59 @Test <lambda>null60 fun testImmediateDispatcher() = runTest { 61 Dispatchers.setMain(ImmediateDispatcher()) 62 expect(1) 63 withContext(Dispatchers.Main) { 64 expect(3) 65 } 66 67 Dispatchers.setMain(RegularDispatcher()) 68 withContext(Dispatchers.Main) { 69 expect(6) 70 } 71 72 finish(7) 73 } 74 75 private inner class ImmediateDispatcher : CoroutineDispatcher() { isDispatchNeedednull76 override fun isDispatchNeeded(context: CoroutineContext): Boolean { 77 expect(2) 78 return false 79 } 80 dispatchnull81 override fun dispatch(context: CoroutineContext, block: Runnable) = throw RuntimeException("Shouldn't be reached") 82 } 83 84 private inner class RegularDispatcher : CoroutineDispatcher() { 85 override fun isDispatchNeeded(context: CoroutineContext): Boolean { 86 expect(4) 87 return true 88 } 89 90 override fun dispatch(context: CoroutineContext, block: Runnable) { 91 expect(5) 92 block.run() 93 } 94 } 95 } 96