Skip to content

Commit 0fd8cac

Browse files
committed
refactor: compatibility tests for spring
1 parent 86a21c6 commit 0fd8cac

File tree

47 files changed

+625
-1264
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+625
-1264
lines changed

build.gradle.kts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,14 @@ apiValidation {
2424
"spring-4x-example",
2525
"spring-standalone-example",
2626
"spring-streams-example",
27-
"tests"
27+
"tests",
28+
"spring-test-fixtures",
29+
"spring-2x-kafka-tests",
30+
"spring-3x-kafka-tests",
31+
"spring-4x-kafka-tests",
32+
"spring-4x-tests",
33+
"spring-3x-tests",
34+
"spring-2x-tests"
2835
)
2936
}
3037
kover {

settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ include(
1919
"starters:ktor:stove-ktor-testing-e2e",
2020
"starters:spring:stove-spring-testing-e2e",
2121
"starters:spring:stove-spring-testing-e2e-kafka",
22+
"starters:spring:tests:spring-test-fixtures",
2223
"starters:spring:tests:spring-2x-tests",
2324
"starters:spring:tests:spring-2x-kafka-tests",
2425
"starters:spring:tests:spring-3x-tests",

starters/spring/tests/spring-2x-kafka-tests/api/spring-2x-kafka-tests.api

Whitespace-only changes.
Lines changed: 1 addition & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,15 @@
1-
import com.google.protobuf.gradle.id
2-
3-
plugins {
4-
alias(libs.plugins.protobuf)
5-
}
6-
71
dependencies {
82
api(projects.starters.spring.stoveSpringTestingE2eKafka)
93
implementation(libs.spring.boot.kafka)
104
}
115

126
dependencies {
13-
testAnnotationProcessor(libs.spring.boot.annotationProcessor)
7+
testImplementation(testFixtures(projects.starters.spring.tests.springTestFixtures))
148
testImplementation(libs.spring.boot.autoconfigure)
159
testImplementation(projects.starters.spring.tests.spring2xTests)
1610
testImplementation(libs.logback.classic)
17-
testImplementation(libs.google.protobuf.kotlin)
18-
testImplementation(libs.kafka.streams.protobuf.serde)
1911
}
2012

2113
tasks.test.configure {
2214
systemProperty("kotest.framework.config.fqn", "com.trendyol.stove.testing.e2e.kafka.Setup")
2315
}
24-
25-
protobuf {
26-
protoc {
27-
artifact = libs.protoc.get().toString()
28-
}
29-
30-
generateProtoTasks {
31-
all().forEach {
32-
it.descriptorSetOptions.includeSourceInfo = true
33-
it.descriptorSetOptions.includeImports = true
34-
it.builtins { id("kotlin") }
35-
}
36-
}
37-
}

starters/spring/tests/spring-2x-kafka-tests/src/test/kotlin/com/trendyol/stove/testing/e2e/kafka/KotestExtensions.kt

Lines changed: 0 additions & 33 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,16 @@
11
package com.trendyol.stove.testing.e2e.kafka.protobufserde
22

3-
import com.google.protobuf.Message
4-
import com.trendyol.stove.spring.testing.e2e.kafka.v1.*
5-
import com.trendyol.stove.spring.testing.e2e.kafka.v1.Example.*
63
import com.trendyol.stove.testing.e2e.kafka.*
7-
import com.trendyol.stove.testing.e2e.serialization.StoveSerde
84
import com.trendyol.stove.testing.e2e.springBoot
95
import com.trendyol.stove.testing.e2e.system.TestSystem
10-
import com.trendyol.stove.testing.e2e.system.TestSystem.Companion.validate
11-
import io.confluent.kafka.streams.serdes.protobuf.KafkaProtobufSerde
12-
import io.kotest.core.spec.style.ShouldSpec
136
import org.springframework.context.support.beans
14-
import kotlin.random.Random
157

16-
@Suppress("UNCHECKED_CAST")
17-
class StoveProtobufSerde : StoveSerde<Any, ByteArray> {
18-
private val parseFromMethod = "parseFrom"
19-
private val protobufSerde: KafkaProtobufSerde<Message> = KafkaRegistry.createSerde()
20-
21-
override fun serialize(value: Any): ByteArray = protobufSerde.serializer().serialize("any", value as Message)
22-
23-
override fun <T : Any> deserialize(value: ByteArray, clazz: Class<T>): T {
24-
val incoming: Message = protobufSerde.deserializer().deserialize("any", value)
25-
incoming.isAssignableFrom(clazz).also { isAssignableFrom ->
26-
require(isAssignableFrom) {
27-
"Expected '${clazz.simpleName}' but got '${incoming.descriptorForType.name}'. " +
28-
"This could be transient ser/de problem since the message stream is constantly checked if the expected message is arrived, " +
29-
"so you can ignore this error if you are sure that the message is the expected one."
30-
}
31-
}
32-
33-
val parseFromMethod = clazz.getDeclaredMethod(parseFromMethod, ByteArray::class.java)
34-
val parsed = parseFromMethod(incoming, incoming.toByteArray()) as T
35-
return parsed
36-
}
37-
}
38-
39-
private fun Message.isAssignableFrom(clazz: Class<*>): Boolean = this.descriptorForType.name == clazz.simpleName
40-
41-
class ProtobufSerdeKafkaSystemTest :
42-
ShouldSpec({
8+
/**
9+
* Spring Boot 2.x Protobuf Serde Kafka tests.
10+
* Test cases are inherited from [ProtobufSerdeKafkaSystemTests] in fixtures.
11+
*/
12+
class Boot2xProtobufSerdeKafkaSystemTest : ProtobufSerdeKafkaSystemTests() {
13+
init {
4314
beforeSpec {
4415
TestSystem()
4516
.with {
@@ -77,43 +48,5 @@ class ProtobufSerdeKafkaSystemTest :
7748
afterSpec {
7849
TestSystem.stop()
7950
}
80-
81-
should("publish and consume") {
82-
validate {
83-
kafka {
84-
val userId = Random.nextInt().toString()
85-
val productId = Random.nextInt().toString()
86-
val product = product {
87-
id = productId
88-
name = "product-${Random.nextInt()}"
89-
price = Random.nextDouble()
90-
currency = "eur"
91-
description = "description-${Random.nextInt()}"
92-
}
93-
val headers = mapOf("x-user-id" to userId)
94-
publish("topic-protobuf", product, headers = headers)
95-
shouldBePublished<Product> {
96-
actual == product && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic-protobuf"
97-
}
98-
shouldBeConsumed<Product> {
99-
actual == product && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic-protobuf"
100-
}
101-
102-
val orderId = Random.nextInt().toString()
103-
val order = order {
104-
id = orderId
105-
customerId = userId
106-
products += product
107-
}
108-
publish("topic-protobuf", order, headers = headers)
109-
shouldBePublished<Order> {
110-
actual == order && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic-protobuf"
111-
}
112-
113-
shouldBeConsumed<Order> {
114-
actual == order && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic-protobuf"
115-
}
116-
}
117-
}
118-
}
119-
})
51+
}
52+
}

starters/spring/tests/spring-2x-kafka-tests/src/test/kotlin/com/trendyol/stove/testing/e2e/kafka/protobufserde/app.kt

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
package com.trendyol.stove.testing.e2e.kafka.protobufserde
22

33
import com.google.protobuf.Message
4-
import com.trendyol.stove.testing.e2e.kafka.StoveBusinessException
5-
import io.confluent.kafka.schemaregistry.testutil.MockSchemaRegistry
6-
import io.confluent.kafka.serializers.AbstractKafkaSchemaSerDeConfig.SCHEMA_REGISTRY_URL_CONFIG
4+
import com.trendyol.stove.testing.e2e.kafka.KafkaRegistry // From fixtures
5+
import com.trendyol.stove.testing.e2e.kafka.StoveBusinessException // From fixtures
76
import io.confluent.kafka.streams.serdes.protobuf.KafkaProtobufSerde
87
import org.apache.kafka.clients.consumer.ConsumerConfig
98
import org.apache.kafka.clients.producer.ProducerConfig
@@ -20,30 +19,6 @@ import org.springframework.kafka.core.*
2019
import org.springframework.kafka.listener.*
2120
import org.springframework.util.backoff.FixedBackOff
2221

23-
sealed class KafkaRegistry(
24-
open val url: String
25-
) {
26-
object Mock : KafkaRegistry("mock://mock-registry")
27-
28-
data class Defined(
29-
override val url: String
30-
) : KafkaRegistry(url)
31-
32-
companion object {
33-
fun createSerde(registry: KafkaRegistry = Mock): KafkaProtobufSerde<Message> {
34-
val schemaRegistryClient = when (registry) {
35-
is Mock -> MockSchemaRegistry.getClientForScope("mock-registry")
36-
is Defined -> MockSchemaRegistry.getClientForScope(registry.url)
37-
}
38-
val serde: KafkaProtobufSerde<Message> = KafkaProtobufSerde<Message>(schemaRegistryClient)
39-
val serdeConfig: MutableMap<String, Any?> = HashMap()
40-
serdeConfig[SCHEMA_REGISTRY_URL_CONFIG] = registry.url
41-
serde.configure(serdeConfig, false)
42-
return serde
43-
}
44-
}
45-
}
46-
4722
class ProtobufValueSerializer<T : Any> : Serializer<T> {
4823
private val protobufSerde: KafkaProtobufSerde<Message> = KafkaRegistry.createSerde()
4924

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,4 @@
11
package com.trendyol.stove.testing.e2e.kafka
22

3-
import io.kotest.core.config.AbstractProjectConfig
4-
import io.kotest.engine.concurrency.SpecExecutionMode
5-
6-
class Setup : AbstractProjectConfig() {
7-
override val specExecutionMode: SpecExecutionMode = SpecExecutionMode.Sequential
8-
}
9-
10-
class StoveBusinessException(
11-
message: String
12-
) : Exception(message)
3+
/** Spring Boot 2.x Kafka test setup - uses shared fixtures */
4+
class Setup : KafkaTestSetup()
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
package com.trendyol.stove.testing.e2e.kafka.stringserde
22

3-
import arrow.core.some
43
import com.trendyol.stove.testing.e2e.kafka.*
54
import com.trendyol.stove.testing.e2e.serialization.StoveSerde
65
import com.trendyol.stove.testing.e2e.springBoot
76
import com.trendyol.stove.testing.e2e.system.TestSystem
8-
import com.trendyol.stove.testing.e2e.system.TestSystem.Companion.validate
9-
import io.kotest.core.spec.style.ShouldSpec
10-
import io.kotest.matchers.shouldBe
11-
import org.apache.kafka.clients.admin.NewTopic
127
import org.springframework.context.support.beans
13-
import kotlin.random.Random
148

15-
class StringSerdeKafkaSystemTests :
16-
ShouldSpec({
9+
/**
10+
* Spring Boot 2.x String Serde Kafka tests.
11+
* Test cases are inherited from [StringSerdeKafkaSystemTests] in fixtures.
12+
*/
13+
class Boot2xStringSerdeKafkaSystemTests : StringSerdeKafkaSystemTests() {
14+
init {
1715
beforeSpec {
1816
TestSystem()
1917
.with {
@@ -50,78 +48,5 @@ class StringSerdeKafkaSystemTests :
5048
afterSpec {
5149
TestSystem.stop()
5250
}
53-
54-
should("publish and consume") {
55-
validate {
56-
kafka {
57-
val userId = Random.nextInt().toString()
58-
val message =
59-
"this message is coming from ${testCase.descriptor.id.value} and testName is ${testCase.name.name}"
60-
val headers = mapOf("x-user-id" to userId)
61-
publish("topic", message, headers = headers)
62-
shouldBePublished<Any> {
63-
actual == message && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic"
64-
}
65-
shouldBeConsumed<Any> {
66-
actual == message && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic"
67-
}
68-
}
69-
}
70-
}
71-
72-
should("publish and consume with failed consumer") {
73-
shouldThrowMaybe<StoveBusinessException> {
74-
validate {
75-
kafka {
76-
val userId = Random.nextInt().toString()
77-
val message =
78-
"this message is coming from ${testCase.descriptor.id.value} and testName is ${testCase.name.name}"
79-
val headers = mapOf("x-user-id" to userId)
80-
publish("topic-failed", message, headers = headers)
81-
shouldBePublished<Any> {
82-
actual == message && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic-failed"
83-
}
84-
shouldBeFailed<Any> {
85-
actual == message && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic-failed" && reason is StoveBusinessException
86-
}
87-
88-
shouldBePublished<Any> {
89-
actual == message && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic-failed.DLT"
90-
}
91-
}
92-
}
93-
}
94-
}
95-
96-
should("admin operations") {
97-
validate {
98-
kafka {
99-
adminOperations {
100-
val topic = "topic"
101-
createTopics(listOf(NewTopic(topic, 1, 1)))
102-
listTopics().names().get().contains(topic) shouldBe true
103-
deleteTopics(listOf(topic))
104-
listTopics().names().get().contains(topic) shouldBe false
105-
}
106-
}
107-
}
108-
}
109-
110-
should("publish with ser/de") {
111-
validate {
112-
kafka {
113-
val userId = Random.nextInt().toString()
114-
val message =
115-
"this message is coming from ${testCase.descriptor.id.value} and testName is ${testCase.name.name}"
116-
val headers = mapOf("x-user-id" to userId)
117-
publish("topic", message, serde = StoveSerde.jackson.anyJsonStringSerde().some(), headers = headers)
118-
shouldBePublished<String> {
119-
actual == message && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic"
120-
}
121-
shouldBeConsumed<String> {
122-
actual == message && this.metadata.headers["x-user-id"] == userId && this.metadata.topic == "topic"
123-
}
124-
}
125-
}
126-
}
127-
})
51+
}
52+
}

starters/spring/tests/spring-2x-kafka-tests/src/test/kotlin/com/trendyol/stove/testing/e2e/kafka/stringserde/app.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.trendyol.stove.testing.e2e.kafka.stringserde
22

3-
import com.trendyol.stove.testing.e2e.kafka.StoveBusinessException
3+
import com.trendyol.stove.testing.e2e.kafka.StoveBusinessException // From fixtures
44
import org.apache.kafka.clients.consumer.ConsumerConfig
55
import org.apache.kafka.clients.producer.ProducerConfig
66
import org.apache.kafka.common.serialization.Serdes

0 commit comments

Comments
 (0)