Skip to content

Commit e23a63e

Browse files
AdrienAdrien Poupard
Adrien
authored and
Adrien Poupard
committed
Test: Add unit tests for Kotlin arity and wrapper functionalities
This commit adds new unit tests to verify the core logic for Kotlin arity handling and wrapper mechanisms. These tests cover various scenarios including catalogue registration and native type casting for consumers, functions, and suppliers. Signed-off-by: Adrien Poupard <[email protected]>
1 parent ec46f82 commit e23a63e

22 files changed

+3121
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,281 @@
1+
/*
2+
* Copyright 2019-2021 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.cloud.function.kotlin;
18+
19+
import org.junit.jupiter.api.AfterEach;
20+
import org.junit.jupiter.params.ParameterizedTest;
21+
import org.junit.jupiter.params.provider.ValueSource;
22+
23+
import org.springframework.boot.builder.SpringApplicationBuilder;
24+
import org.springframework.cloud.function.context.FunctionCatalog;
25+
import org.springframework.cloud.function.context.catalog.SimpleFunctionRegistry.FunctionInvocationWrapper;
26+
import org.springframework.cloud.function.kotlin.arity.KotlinArityApplication;
27+
import org.springframework.context.support.GenericApplicationContext;
28+
import org.springframework.messaging.Message;
29+
import org.springframework.messaging.support.MessageBuilder;
30+
31+
import static org.assertj.core.api.Assertions.assertThat;
32+
33+
/**
34+
* Tests for different arity functions, suppliers, and consumers in the FunctionCatalog.
35+
*
36+
* @author Adrien Poupard
37+
*/
38+
public class ConsumerArityCatalogueTests {
39+
40+
private GenericApplicationContext context;
41+
42+
private FunctionCatalog catalog;
43+
44+
@AfterEach
45+
public void close() {
46+
if (this.context != null) {
47+
this.context.close();
48+
}
49+
}
50+
51+
@ParameterizedTest
52+
@ValueSource(strings = {
53+
"consumerPlain", "consumerKotlinPlain", "consumerJavaPlain"
54+
})
55+
public void testPlainConsumers(String consumerName) {
56+
create(new Class[] { KotlinArityApplication.class });
57+
58+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
59+
60+
// Test should fail if consumer is not found
61+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
62+
63+
// Verify it's a consumer
64+
assertThat(consumer.isConsumer()).isTrue();
65+
66+
// Plain string consumer
67+
String typeName = consumer.getInputType().getTypeName();
68+
assertThat(typeName).isEqualTo("java.lang.String");
69+
70+
// Just verifying it doesn't throw an exception
71+
consumer.apply("test");
72+
}
73+
74+
@ParameterizedTest
75+
@ValueSource(strings = {"consumerSuspendPlain", "consumerKotlinSuspendPlain"})
76+
public void testSuspendPlainConsumers(String consumerName) {
77+
create(new Class[] { KotlinArityApplication.class });
78+
79+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
80+
81+
// Test should fail if consumer is not found
82+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
83+
84+
// Verify it's a consumer
85+
assertThat(consumer.isConsumer()).isTrue();
86+
87+
String typeName = consumer.getInputType().getTypeName();
88+
89+
// Suspend Plain consumer
90+
assertThat(typeName).isEqualTo("java.lang.String");
91+
consumer.apply("test");
92+
}
93+
94+
@ParameterizedTest
95+
@ValueSource(strings = {"consumerJavaFlow", "consumerKotlinFlow", "consumerFlow"})
96+
public void testFlowConsumerMethods(String consumerName) {
97+
create(new Class[] { KotlinArityApplication.class });
98+
99+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
100+
101+
// Test should fail if consumer is not found
102+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
103+
104+
// Verify it's a consumer
105+
assertThat(consumer.isConsumer()).isTrue();
106+
107+
String typeName = consumer.getInputType().getTypeName();
108+
109+
// Flow consumer
110+
// Note: Spring Cloud Function might convert Kotlin Flow to Reactor Flux
111+
assertThat(typeName.contains("Flux")).isTrue();
112+
// We can't easily create a Flow instance for testing, so we just verify the type
113+
}
114+
115+
@ParameterizedTest
116+
@ValueSource(strings = {"consumerMonoInput", "consumerJavaMonoInput", "consumerKotlinMonoInput"})
117+
public void testMonoInputConsumers(String consumerName) {
118+
create(new Class[] { KotlinArityApplication.class });
119+
120+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
121+
122+
// Test should fail if consumer is not found
123+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
124+
125+
// Verify it's a consumer
126+
assertThat(consumer.isConsumer()).isTrue();
127+
128+
String typeName = consumer.getInputType().getTypeName();
129+
130+
// MonoInput consumer (actually a String consumer that returns Mono<Void>)
131+
assertThat(typeName).isEqualTo("java.lang.String");
132+
consumer.apply("test");
133+
}
134+
135+
@ParameterizedTest
136+
@ValueSource(strings = {"consumerMono", "consumerJavaMono", "consumerKotlinMono"})
137+
public void testMonoConsumers(String consumerName) {
138+
create(new Class[] { KotlinArityApplication.class });
139+
140+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
141+
142+
// Test should fail if consumer is not found
143+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
144+
145+
// Verify it's a consumer
146+
assertThat(consumer.isConsumer()).isTrue();
147+
148+
String typeName = consumer.getInputType().getTypeName();
149+
150+
// Mono consumer
151+
assertThat(typeName).contains("Mono");
152+
// We can't easily test the actual consumption of a Mono, so we just verify the type
153+
}
154+
155+
@ParameterizedTest
156+
@ValueSource(strings = {"consumerFlux", "consumerJavaFlux", "consumerKotlinFlux"})
157+
public void testFluxConsumers(String consumerName) {
158+
create(new Class[] { KotlinArityApplication.class });
159+
160+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
161+
162+
// Test should fail if consumer is not found
163+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
164+
165+
// Verify it's a consumer
166+
assertThat(consumer.isConsumer()).isTrue();
167+
168+
String typeName = consumer.getInputType().getTypeName();
169+
170+
// Flux consumer
171+
assertThat(typeName).contains("Flux");
172+
// We can't easily test the actual consumption of a Flux, so we just verify the type
173+
}
174+
175+
@ParameterizedTest
176+
@ValueSource(strings = {"consumerMessage", "consumerJavaMessage", "consumerKotlinMessage"})
177+
public void testMessageConsumers(String consumerName) {
178+
create(new Class[] { KotlinArityApplication.class });
179+
180+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
181+
182+
// Test should fail if consumer is not found
183+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
184+
185+
// Verify it's a consumer
186+
assertThat(consumer.isConsumer()).isTrue();
187+
188+
String typeName = consumer.getInputType().getTypeName();
189+
190+
// Message consumer
191+
assertThat(typeName).contains("Message");
192+
Message<String> message = MessageBuilder.withPayload("test").build();
193+
consumer.apply(message);
194+
}
195+
196+
@ParameterizedTest
197+
@ValueSource(strings = {"consumerMonoMessage", "consumerJavaMonoMessage", "consumerKotlinMonoMessage"})
198+
public void testMonoMessageConsumers(String consumerName) {
199+
create(new Class[] { KotlinArityApplication.class });
200+
201+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
202+
203+
// Test should fail if consumer is not found
204+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
205+
206+
// Verify it's a consumer
207+
assertThat(consumer.isConsumer()).isTrue();
208+
209+
String typeName = consumer.getInputType().getTypeName();
210+
211+
// Mono<Message> consumer
212+
assertThat(typeName).contains("Mono");
213+
assertThat(typeName).contains("Message");
214+
// We can't easily test the actual consumption of a Mono<Message>, so we just verify the type
215+
}
216+
217+
@ParameterizedTest
218+
@ValueSource(strings = {"consumerSuspendMessage", "consumerKotlinSuspendMessage"})
219+
public void testSuspendMessageConsumers(String consumerName) {
220+
create(new Class[] { KotlinArityApplication.class });
221+
222+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
223+
224+
// Test should fail if consumer is not found
225+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
226+
227+
// Verify it's a consumer
228+
assertThat(consumer.isConsumer()).isTrue();
229+
230+
String typeName = consumer.getInputType().getTypeName();
231+
232+
// Suspend Message consumer
233+
assertThat(typeName).contains("Message");
234+
Message<String> message = MessageBuilder.withPayload("test").build();
235+
consumer.apply(message);
236+
}
237+
238+
@ParameterizedTest
239+
@ValueSource(strings = {"consumerFluxMessage", "consumerJavaFluxMessage", "consumerKotlinFluxMessage"})
240+
public void testFluxMessageConsumers(String consumerName) {
241+
create(new Class[] { KotlinArityApplication.class });
242+
243+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
244+
245+
// Test should fail if consumer is not found
246+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
247+
248+
// Verify it's a consumer
249+
assertThat(consumer.isConsumer()).isTrue();
250+
251+
String typeName = consumer.getInputType().getTypeName();
252+
253+
// Flux<Message> consumer
254+
assertThat(typeName).contains("Flux");
255+
assertThat(typeName).contains("Message");
256+
}
257+
258+
@ParameterizedTest
259+
@ValueSource(strings = {"consumerSuspendFlowMessage", "consumerKotlinSuspendFlowMessage"})
260+
public void testSuspendFlowMessageConsumers(String consumerName) {
261+
create(new Class[] { KotlinArityApplication.class });
262+
263+
FunctionInvocationWrapper consumer = this.catalog.lookup(consumerName);
264+
265+
// Test should fail if consumer is not found
266+
assertThat(consumer).as("Consumer not found: " + consumerName).isNotNull();
267+
268+
// Verify it's a consumer
269+
assertThat(consumer.isConsumer()).isTrue();
270+
271+
String typeName = consumer.getInputType().getTypeName();
272+
273+
assertThat(typeName.contains("Flux")).isTrue();
274+
assertThat(typeName).contains("Message");
275+
}
276+
277+
private void create(Class<?>[] types, String... props) {
278+
this.context = (GenericApplicationContext) new SpringApplicationBuilder(types).properties(props).run();
279+
this.catalog = this.context.getBean(FunctionCatalog.class);
280+
}
281+
}

0 commit comments

Comments
 (0)