Skip to content

Commit 3d8455b

Browse files
committed
Add unit tests for CoroutinesUtils
Closes gh-29968
1 parent fd38c23 commit 3d8455b

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed

spring-core/spring-core.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ dependencies {
8686
testImplementation("com.squareup.okhttp3:mockwebserver")
8787
testImplementation("org.jetbrains.kotlinx:kotlinx-serialization-json")
8888
testImplementation("com.fasterxml.jackson.core:jackson-databind")
89+
testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactor")
8990
testFixturesImplementation("com.google.code.findbugs:jsr305")
9091
testFixturesImplementation("org.junit.platform:junit-platform-launcher")
9192
testFixturesImplementation("org.junit.jupiter:junit-jupiter-api")
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.core
18+
19+
import kotlinx.coroutines.*
20+
import kotlinx.coroutines.flow.Flow
21+
import kotlinx.coroutines.flow.flowOf
22+
import kotlinx.coroutines.reactor.awaitSingle
23+
import org.assertj.core.api.Assertions
24+
import org.junit.jupiter.api.Test
25+
import reactor.core.publisher.Flux
26+
import reactor.core.publisher.Mono
27+
import reactor.test.StepVerifier
28+
import kotlin.coroutines.Continuation
29+
import kotlin.coroutines.coroutineContext
30+
31+
class KotlinCoroutinesUtilsTests {
32+
33+
@Test
34+
fun deferredToMono() {
35+
runBlocking {
36+
val deferred: Deferred<String> = async(Dispatchers.IO) {
37+
delay(10)
38+
"foo"
39+
}
40+
val mono = CoroutinesUtils.deferredToMono(deferred)
41+
StepVerifier.create(mono)
42+
.expectNext("foo")
43+
.expectComplete()
44+
.verify()
45+
}
46+
}
47+
48+
@Test
49+
fun monoToDeferred() {
50+
runBlocking {
51+
val mono = Mono.just("foo")
52+
val deferred = CoroutinesUtils.monoToDeferred(mono)
53+
Assertions.assertThat(deferred.await()).isEqualTo("foo")
54+
}
55+
}
56+
57+
@Test
58+
fun invokeSuspendingFunctionWithNullContinuationParameter() {
59+
val method = KotlinCoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunction", String::class.java, Continuation::class.java)
60+
val publisher = CoroutinesUtils.invokeSuspendingFunction(method, this, "foo", null)
61+
Assertions.assertThat(publisher).isInstanceOf(Mono::class.java)
62+
StepVerifier.create(publisher)
63+
.expectNext("foo")
64+
.expectComplete()
65+
.verify()
66+
}
67+
68+
@Test
69+
fun invokeSuspendingFunctionWithoutContinuationParameter() {
70+
val method = KotlinCoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunction", String::class.java, Continuation::class.java)
71+
val publisher = CoroutinesUtils.invokeSuspendingFunction(method, this, "foo")
72+
Assertions.assertThat(publisher).isInstanceOf(Mono::class.java)
73+
StepVerifier.create(publisher)
74+
.expectNext("foo")
75+
.expectComplete()
76+
.verify()
77+
}
78+
79+
@Test
80+
fun invokeNonSuspendingFunction() {
81+
val method = KotlinCoroutinesUtilsTests::class.java.getDeclaredMethod("nonSuspendingFunction", String::class.java)
82+
Assertions.assertThatIllegalArgumentException().isThrownBy { CoroutinesUtils.invokeSuspendingFunction(method, this, "foo") }
83+
}
84+
85+
@Test
86+
fun invokeSuspendingFunctionWithFlow() {
87+
val method = KotlinCoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunctionWithFlow", Continuation::class.java)
88+
val publisher = CoroutinesUtils.invokeSuspendingFunction(method, this)
89+
Assertions.assertThat(publisher).isInstanceOf(Flux::class.java)
90+
StepVerifier.create(publisher)
91+
.expectNext("foo")
92+
.expectNext("bar")
93+
.expectComplete()
94+
.verify()
95+
}
96+
97+
@Test
98+
fun invokeSuspendingFunctionWithNullContinuationParameterAndContext() {
99+
val method = KotlinCoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunctionWithContext", String::class.java, Continuation::class.java)
100+
val context = CoroutineName("name")
101+
val mono = CoroutinesUtils.invokeSuspendingFunction(context, method, this, "foo", null) as Mono
102+
runBlocking {
103+
Assertions.assertThat(mono.awaitSingle()).isEqualTo("foo")
104+
}
105+
}
106+
107+
@Test
108+
fun invokeSuspendingFunctionWithoutContinuationParameterAndContext() {
109+
val method = KotlinCoroutinesUtilsTests::class.java.getDeclaredMethod("suspendingFunctionWithContext", String::class.java, Continuation::class.java)
110+
val context = CoroutineName("name")
111+
val mono = CoroutinesUtils.invokeSuspendingFunction(context, method, this, "foo") as Mono
112+
runBlocking {
113+
Assertions.assertThat(mono.awaitSingle()).isEqualTo("foo")
114+
}
115+
}
116+
117+
@Test
118+
fun invokeNonSuspendingFunctionWithContext() {
119+
val method = KotlinCoroutinesUtilsTests::class.java.getDeclaredMethod("nonSuspendingFunction", String::class.java)
120+
Assertions.assertThatIllegalArgumentException().isThrownBy { CoroutinesUtils.invokeSuspendingFunction(method, this, "foo") }
121+
}
122+
123+
suspend fun suspendingFunction(value: String): String {
124+
delay(10)
125+
return value
126+
}
127+
128+
suspend fun suspendingFunctionWithFlow(): Flow<String> {
129+
delay(10)
130+
return flowOf("foo", "bar")
131+
}
132+
133+
fun nonSuspendingFunction(value: String): String {
134+
return value
135+
}
136+
137+
suspend fun suspendingFunctionWithContext(value: String): String {
138+
delay(10)
139+
Assertions.assertThat(coroutineContext[CoroutineName]?.name).isEqualTo("name")
140+
return value
141+
}
142+
143+
}

0 commit comments

Comments
 (0)