@@ -47,8 +47,8 @@ public interface TestCoroutineScope: CoroutineScope {
47
47
/* *
48
48
* Reports an exception so that it is thrown on [cleanupTestCoroutines].
49
49
*
50
- * If several exceptions are reported, only the first one will be thrown, and the other ones will be printed to the
51
- * console .
50
+ * If several exceptions are reported, only the first one will be thrown, and the other ones will be suppressed by
51
+ * it .
52
52
*
53
53
* @throws IllegalStateException with the [Throwable.cause] set to [throwable] if [cleanupTestCoroutines] was
54
54
* already called.
@@ -85,7 +85,11 @@ private class TestCoroutineScopeImpl(
85
85
val delayController = coroutineContext.delayController
86
86
var hasUncompletedJobs = false
87
87
if (delayController != null ) {
88
- delayController.cleanupTestCoroutines()
88
+ try {
89
+ delayController.cleanupTestCoroutines()
90
+ } catch (e: UncompletedCoroutinesError ) {
91
+ hasUncompletedJobs = true
92
+ }
89
93
} else {
90
94
testScheduler.runCurrent()
91
95
if (! testScheduler.isIdle()) {
@@ -98,20 +102,27 @@ private class TestCoroutineScopeImpl(
98
102
cleanedUp = true
99
103
}
100
104
exceptions.apply {
101
- drop(1 ).forEach { it.printStackTrace() }
102
- singleOrNull()?.let { throw it }
103
- }
104
- if (hasUncompletedJobs) {
105
- throw UncompletedCoroutinesError (
106
- " Unfinished coroutines during teardown. Ensure all coroutines are" +
107
- " completed or cancelled by your test."
108
- )
105
+ firstOrNull()?.let {
106
+ val toThrow = it
107
+ drop(1 ).forEach { toThrow.addSuppressed(it) }
108
+ ownJob?.completeExceptionally(toThrow)
109
+ throw toThrow
110
+ }
109
111
}
110
- val jobs = coroutineContext.activeJobs()
111
- if ((jobs - initialJobs).isNotEmpty()) {
112
- val exception = UncompletedCoroutinesError (" Test finished with active jobs: $jobs " )
113
- ownJob?.completeExceptionally(exception)
114
- throw exception
112
+ try {
113
+ if (hasUncompletedJobs) {
114
+ throw UncompletedCoroutinesError (
115
+ " Unfinished coroutines during teardown. Ensure all coroutines are" +
116
+ " completed or cancelled by your test."
117
+ )
118
+ }
119
+ val jobs = coroutineContext.activeJobs()
120
+ if ((jobs - initialJobs).isNotEmpty()) {
121
+ throw UncompletedCoroutinesError (" Test finished with active jobs: $jobs " )
122
+ }
123
+ } catch (e: UncompletedCoroutinesError ) {
124
+ ownJob?.completeExceptionally(e)
125
+ throw e
115
126
}
116
127
ownJob?.complete()
117
128
}
0 commit comments