Skip to content

Commit 3888fd4

Browse files
committed
Fix 'TestCoroutineScheduler' being ignored on 'TestCoroutineScope' creation
1 parent be58ef6 commit 3888fd4

File tree

2 files changed

+41
-8
lines changed

2 files changed

+41
-8
lines changed

kotlinx-coroutines-test/common/src/TestBuilders.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ internal fun CoroutineContext.checkTestScopeArguments(): Pair<CoroutineContext,
9696
dispatcher
9797
}
9898
null -> {
99-
scheduler = TestCoroutineScheduler()
99+
scheduler = get(TestCoroutineScheduler) ?: TestCoroutineScheduler()
100100
TestCoroutineDispatcher(scheduler)
101101
}
102102
else -> throw IllegalArgumentException("Dispatcher must implement TestDispatcher: $dispatcher")

kotlinx-coroutines-test/common/test/TestCoroutineScopeTest.kt

+40-7
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,54 @@
55
package kotlinx.coroutines.test
66

77
import kotlinx.coroutines.*
8+
import kotlin.coroutines.*
89
import kotlin.test.*
910

1011
class TestCoroutineScopeTest {
12+
/** Tests failing to create a [TestCoroutineScope] with incorrect contexts. */
1113
@Test
12-
fun whenGivenInvalidExceptionHandler_throwsException() {
13-
val handler = CoroutineExceptionHandler { _, _ -> }
14-
assertFails {
15-
TestCoroutineScope(handler)
14+
fun testCreateThrowsOnInvalidArguments() {
15+
for (ctx in invalidContexts) {
16+
assertFailsWith<IllegalArgumentException> {
17+
TestCoroutineScope(ctx)
18+
}
1619
}
1720
}
1821

22+
/** Tests that a newly-created [TestCoroutineScope] provides the correct scheduler. */
1923
@Test
20-
fun whenGivenInvalidDispatcher_throwsException() {
21-
assertFails {
22-
TestCoroutineScope(Dispatchers.Default)
24+
fun testCreateProvidesScheduler() {
25+
// Creates a new scheduler.
26+
run {
27+
val scope = TestCoroutineScope()
28+
assertNotNull(scope.coroutineContext[TestCoroutineScheduler])
29+
}
30+
// Reuses the scheduler that the dispatcher is linked to.
31+
run {
32+
val dispatcher = TestCoroutineDispatcher()
33+
val scope = TestCoroutineScope(dispatcher)
34+
assertSame(dispatcher.scheduler, scope.coroutineContext[TestCoroutineScheduler])
35+
}
36+
// Uses the scheduler passed to it.
37+
run {
38+
val scheduler = TestCoroutineScheduler()
39+
val scope = TestCoroutineScope(scheduler)
40+
assertSame(scheduler, scope.coroutineContext[TestCoroutineScheduler])
41+
assertSame(scheduler, (scope.coroutineContext[ContinuationInterceptor] as TestDispatcher).scheduler)
42+
}
43+
// Doesn't touch the passed dispatcher and the scheduler if they match.
44+
run {
45+
val scheduler = TestCoroutineScheduler()
46+
val dispatcher = TestCoroutineDispatcher(scheduler)
47+
val scope = TestCoroutineScope(scheduler + dispatcher)
48+
assertSame(scheduler, scope.coroutineContext[TestCoroutineScheduler])
49+
assertSame(dispatcher, scope.coroutineContext[ContinuationInterceptor])
2350
}
2451
}
52+
53+
private val invalidContexts = listOf(
54+
Dispatchers.Default, // not a [TestDispatcher]
55+
TestCoroutineDispatcher() + TestCoroutineScheduler(), // the dispatcher is not linked to the scheduler
56+
CoroutineExceptionHandler { _, _ -> }, // not an `UncaughtExceptionCaptor`
57+
)
2558
}

0 commit comments

Comments
 (0)