diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 678405245..6e5739c01 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -1,3 +1,14 @@ plugins { id 'groovy-gradle-plugin' } +repositories { + gradlePluginPortal() + mavenCentral() +} + +dependencies { + implementation libs.gradle.micronaut + implementation libs.gradle.kotlin + implementation libs.gradle.kotlin.allopen + implementation libs.gradle.kotlin.noarg +} diff --git a/buildSrc/settings.gradle b/buildSrc/settings.gradle index 6f31e6ef7..08975252b 100644 --- a/buildSrc/settings.gradle +++ b/buildSrc/settings.gradle @@ -1,3 +1,4 @@ +rootProject.name = 'rabbitmq-parent' dependencyResolutionManagement { versionCatalogs { libs { diff --git a/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle b/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle index 5edce0561..d632e272b 100644 --- a/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle +++ b/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-examples.gradle @@ -1,13 +1,27 @@ plugins { id 'io.micronaut.build.internal.rabbitmq-base' + id "io.micronaut.application" + id "io.micronaut.test-resources" } dependencies { testImplementation projects.micronautRabbitmq - - testImplementation mn.micronaut.inject testImplementation mn.reactor testImplementation mnSerde.micronaut.serde.support testImplementation mnSerde.micronaut.serde.jackson - testImplementation libs.testcontainers + testImplementation libs.awaitility + testImplementation 'io.micronaut.testresources:micronaut-test-resources-client' +} +configurations.all { + resolutionStrategy.dependencySubstitution { + substitute module('io.micronaut.rabbitmq:micronaut-rabbitmq') using project(':micronaut-rabbitmq') + } +} +micronaut { + version libs.versions.micronaut.platform.get() + testRuntime "junit5" + testResources { + clientTimeout = 300 + additionalModules.add(RABBITMQ) + } } diff --git a/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-native-tests.gradle b/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-native-tests.gradle new file mode 100644 index 000000000..221e91eae --- /dev/null +++ b/buildSrc/src/main/groovy/io.micronaut.build.internal.rabbitmq-native-tests.gradle @@ -0,0 +1,14 @@ +plugins { + id 'io.micronaut.build.internal.rabbitmq-examples' + id 'org.graalvm.buildtools.native' +} + +tasks.named("check") { task -> + def graal = ["jvmci.Compiler", "java.vendor.version", "java.vendor"].any { + System.getProperty(it)?.toLowerCase(Locale.ENGLISH)?.contains("graal") + } + if (graal) { + task.dependsOn("nativeTest") + } +} + diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/AbstractRabbitMQTest.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/AbstractRabbitMQTest.groovy deleted file mode 100644 index 274c2f5c0..000000000 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/AbstractRabbitMQTest.groovy +++ /dev/null @@ -1,39 +0,0 @@ -package io.micronaut.rabbitmq - -import io.micronaut.context.ApplicationContext -import org.testcontainers.containers.GenericContainer -import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy -import spock.lang.Specification -import spock.util.concurrent.PollingConditions - -abstract class AbstractRabbitMQTest extends Specification { - - static GenericContainer rabbitContainer = - new GenericContainer("library/rabbitmq:3.7") - .withExposedPorts(5672) - .waitingFor(new LogMessageWaitStrategy().withRegEx("(?s).*Server startup complete.*")) - - protected ApplicationContext applicationContext - protected PollingConditions conditions = new PollingConditions(timeout: 5) - - protected void startContext() { - applicationContext = ApplicationContext.run(configuration, "test") - } - - protected Map getConfiguration() { - rabbitContainer.start() - - ["rabbitmq.port": rabbitContainer.getMappedPort(5672), - "spec.name" : getClass().simpleName] as Map - } - - protected void waitFor(Closure conditionEvaluator) { - conditions.eventually conditionEvaluator - } - - void cleanup() { - rabbitContainer.stop() - - applicationContext?.close() - } -} diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.groovy index ccf57bef3..f886ba713 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.groovy @@ -1,26 +1,35 @@ package io.micronaut.rabbitmq.docs.consumer.acknowledge.type -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class AcknowledgeSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await + +@MicronautTest +@Property(name = "spec.name", value = "AcknowledgeSpec") +class AcknowledgeSpec extends Specification { + + @Inject ProductClient productClient + @Inject ProductListener productListener void "test acking with an acknowledgement argument"() { - startContext() when: // tag::producer[] -ProductClient productClient = applicationContext.getBean(ProductClient) productClient.send("message body".bytes) productClient.send("message body".bytes) productClient.send("message body".bytes) productClient.send("message body".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.messageCount.get() == 5 + } then: - waitFor { - assert productListener.messageCount.get() == 5 - } + productListener.messageCount.get() == 5 } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.groovy index c1652b6cf..5b62ba38d 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.groovy @@ -1,21 +1,30 @@ package io.micronaut.rabbitmq.docs.consumer.concurrent -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class ConcurrentSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await + + +@MicronautTest +@Property(name = "spec.name", value = "ConcurrentSpec") +class ConcurrentSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener void "test concurrent consumers"() { - startContext() when: - ProductClient productClient = applicationContext.getBean(ProductClient) 4.times { productClient.send("body".bytes) } - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.threads.size() == 4 + } then: - waitFor { - assert productListener.threads.size() == 4 - } + productListener.threads.size() == 4 } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.groovy index 38115b276..e75b88996 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.groovy @@ -1,32 +1,49 @@ package io.micronaut.rabbitmq.docs.consumer.connection -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import io.micronaut.test.support.TestPropertyProvider +import io.micronaut.testresources.client.TestResourcesClientFactory +import jakarta.inject.Inject +import spock.lang.Specification -class ConnectionSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await + + +@MicronautTest(rebuildContext = true) +@Property(name = "spec.name", value = "ConnectionSpec") +class ConnectionSpec extends Specification implements TestPropertyProvider { + @Inject ProductClient productClient + @Inject ProductListener productListener void "test product client and listener"() { - startContext() when: // tag::producer[] - def productClient = applicationContext.getBean(ProductClient) productClient.send("connection-test".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.messageLengths.size() == 1 && + productListener.messageLengths[0] == "connection-test" + } then: - waitFor { - assert productListener.messageLengths.size() == 1 - assert productListener.messageLengths[0] == "connection-test" - } + productListener.messageLengths.size() == 1 + productListener.messageLengths[0] == "connection-test" cleanup: // Finding that the context is closing the channel before ack is sent sleep 200 } - protected Map getConfiguration() { - super.configuration + ["rabbitmq.servers.product-cluster.port": super.configuration.remove("rabbitmq.port")] + @Override + Map getProperties() { + var client = TestResourcesClientFactory.fromSystemProperties().get(); + var rabbitURI = client.resolve("rabbitmq.uri", Map.of(), Map.of()); + return rabbitURI + .map(uri -> Map.of("rabbitmq.servers.product-cluster.port", String.valueOf(URI.create(uri).getPort()))) + .orElse(Collections.emptyMap()); } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.groovy index 85a5417e1..f3406250e 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.groovy @@ -1,25 +1,32 @@ package io.micronaut.rabbitmq.docs.consumer.custom.annotation -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class DeliveryTagSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await + +@MicronautTest +@Property(name = "spec.name", value = "DeliveryTagSpec") +class DeliveryTagSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener void "test using a custom annotation binder"() { - startContext() when: // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient) productClient.send("body".bytes) productClient.send("body2".bytes) productClient.send("body3".bytes) // end::producer[] - - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.messages.size() == 3 + } then: - waitFor { - assert productListener.messages.size() == 3 - } + productListener.messages.size() == 3 } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.groovy index 4782ad6a9..a504518fe 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.groovy @@ -1,37 +1,46 @@ package io.micronaut.rabbitmq.docs.consumer.custom.type -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class ProductInfoSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await - void "test using a custom type binder"() { - startContext() +@MicronautTest +@Property(name = "spec.name", value = "ProductInfoSpec") +class ProductInfoSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener + + void "test using a custom type binder"() { when: // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient) productClient.send("body".bytes) productClient.send("medium", 20L, "body2".bytes) productClient.send(null, 30L, "body3".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) + + await().atMost(10, SECONDS).until { + productListener.messages.size() == 3 + } then: - waitFor { - assert productListener.messages.size() == 3 + productListener.messages.size() == 3 - assert productListener.messages.find({ pi -> - pi.size == "small" && pi.count == 10 && pi.sealed - }) != null + productListener.messages.find({ pi -> + pi.size == "small" && pi.count == 10 && pi.sealed + }) != null - assert productListener.messages.find({ pi -> - pi.size == "medium" && pi.count == 20 && pi.sealed - }) != null + productListener.messages.find({ pi -> + pi.size == "medium" && pi.count == 20 && pi.sealed + }) != null - assert productListener.messages.find({ pi -> - pi.size == null && pi.count == 30 && pi.sealed - }) != null - } + productListener.messages.find({ pi -> + pi.size == null && pi.count == 30 && pi.sealed + }) != null } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.groovy index ece5f3737..6c4e74e80 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.groovy @@ -1,28 +1,33 @@ package io.micronaut.rabbitmq.docs.consumer.executor -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class CustomExecutorSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await - void "test product client and listener"() { - startContext() +@MicronautTest(rebuildContext = true) +@Property(name = "spec.name", value = "CustomExecutorSpec") +@Property(name = "micronaut.executors.product-listener.type", value = "FIXED") +class CustomExecutorSpec extends Specification { + + @Inject ProductClient productClient + @Inject ProductListener productListener + void "test product client and listener"() { when: // tag::producer[] - def productClient = applicationContext.getBean(ProductClient) productClient.send("custom-executor-test".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) - - then: - waitFor { - assert productListener.messageLengths.size() == 1 - assert productListener.messageLengths[0] == "custom-executor-test" + await().atMost(10, SECONDS).until { + productListener.messageLengths.size() == 1 } - } - protected Map getConfiguration() { - super.configuration + ["micronaut.executors.product-listener.type": "FIXED"] + then: + productListener.messageLengths.size() == 1 + productListener.messageLengths[0] == "custom-executor-test" } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.groovy index 600d4f10d..ddfdfd1be 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.groovy @@ -1,28 +1,36 @@ package io.micronaut.rabbitmq.docs.consumer.types -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class TypeBindingSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await - void "test publishing and receiving rabbitmq types"() { - startContext() +@MicronautTest +@Property(name = "spec.name", value = "TypeBindingSpec") +class TypeBindingSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener + + void "test publishing and receiving rabbitmq types"() { when: // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient) productClient.send("body".bytes, "text/html") productClient.send("body2".bytes, "application/json") productClient.send("body3".bytes, "text/xml") // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.messages.size() == 3 + } then: - waitFor { - assert productListener.messages.size() == 3 - assert productListener.messages.contains("exchange: [], routingKey: [product], contentType: [text/html]") - assert productListener.messages.contains("exchange: [], routingKey: [product], contentType: [application/json]") - assert productListener.messages.contains("exchange: [], routingKey: [product], contentType: [text/xml]") - } + productListener.messages.size() == 3 + productListener.messages.contains("exchange: [], routingKey: [product], contentType: [text/html]") + productListener.messages.contains("exchange: [], routingKey: [product], contentType: [application/json]") + productListener.messages.contains("exchange: [], routingKey: [product], contentType: [text/xml]") } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.groovy index 265c4262a..45a714ca9 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.groovy @@ -1,16 +1,22 @@ package io.micronaut.rabbitmq.docs.exchange -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class CustomExchangeSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await - void "test using a custom exchange"() { - given: - startContext() - AnimalClient client = applicationContext.getBean(AnimalClient) - AnimalListener listener = applicationContext.getBean(AnimalListener) +@MicronautTest +@Property(name = "spec.name", value = "CustomExchangeSpec") +class CustomExchangeSpec extends Specification { + + @Inject AnimalClient client + @Inject AnimalListener listener + void "test using a custom exchange"() { when: // tag::producer[] client.send(new Cat("Whiskers", 9)) @@ -18,26 +24,27 @@ class CustomExchangeSpec extends AbstractRabbitMQTest { client.send(new Snake("Buttercup", false)) client.send(new Snake("Monty the Python", true)) // end::producer[] + await().atMost(10, SECONDS).until { + listener.receivedAnimals.size() == 4 + } then: - waitFor { - assert listener.receivedAnimals.size() == 4 + assert listener.receivedAnimals.size() == 4 - assert listener.receivedAnimals.find({ animal -> - animal instanceof Cat && animal.name == "Whiskers" && ((Cat) animal).lives == 9 - }) != null + assert listener.receivedAnimals.find({ animal -> + animal instanceof Cat && animal.name == "Whiskers" && ((Cat) animal).lives == 9 + }) != null - assert listener.receivedAnimals.find({ animal -> - animal instanceof Cat && animal.name == "Mr. Bigglesworth" && ((Cat) animal).lives == 8 - }) != null + assert listener.receivedAnimals.find({ animal -> + animal instanceof Cat && animal.name == "Mr. Bigglesworth" && ((Cat) animal).lives == 8 + }) != null - assert listener.receivedAnimals.find({ animal -> - animal instanceof Snake && animal.name == "Buttercup" && !((Snake) animal).venomous - }) != null + assert listener.receivedAnimals.find({ animal -> + animal instanceof Snake && animal.name == "Buttercup" && !((Snake) animal).venomous + }) != null - assert listener.receivedAnimals.find({ animal -> - animal instanceof Snake && animal.name == "Monty the Python" && ((Snake) animal).venomous - }) != null - } + assert listener.receivedAnimals.find({ animal -> + animal instanceof Snake && animal.name == "Monty the Python" && ((Snake) animal).venomous + }) != null } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/headers/HeadersSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/headers/HeadersSpec.groovy index 5cdf58623..fd7ad3c53 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/headers/HeadersSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/headers/HeadersSpec.groovy @@ -1,29 +1,38 @@ package io.micronaut.rabbitmq.docs.headers -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class HeadersSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await + + +@MicronautTest +@Property(name = "spec.name", value = "HeadersSpec") +class HeadersSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener void "test publishing and receiving headers"() { when: - startContext() // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient) productClient.send("body".bytes) productClient.send("medium", 20L, "body2".bytes) productClient.send(null, 30L, "body3".bytes) productClient.send([productSize: "large", "x-product-count": 40L], "body4".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.messageProperties.size() == 4 + } then: - waitFor { - assert productListener.messageProperties.size() == 4 - assert productListener.messageProperties.contains("true|10|small") - assert productListener.messageProperties.contains("true|20|medium") - assert productListener.messageProperties.contains("true|30|null") - assert productListener.messageProperties.contains("true|40|large") - } + productListener.messageProperties.size() == 4 + productListener.messageProperties.contains("true|10|small") + productListener.messageProperties.contains("true|20|medium") + productListener.messageProperties.contains("true|30|null") + productListener.messageProperties.contains("true|40|large") } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/parameters/BindingSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/parameters/BindingSpec.groovy index 45215f36b..8368bc301 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/parameters/BindingSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/parameters/BindingSpec.groovy @@ -1,26 +1,33 @@ package io.micronaut.rabbitmq.docs.parameters -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class BindingSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await - void "test dynamic binding"() { - startContext() +@MicronautTest +@Property(name = "spec.name", value = "BindingSpec") +class BindingSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener + + void "test dynamic binding"() { when: // tag::producer[] - def productClient = applicationContext.getBean(ProductClient) productClient.send("message body".bytes) productClient.send("product", "message body2".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) - - then: - waitFor { - assert productListener.messageLengths.size() == 2 - assert productListener.messageLengths.contains(12) - assert productListener.messageLengths.contains(13) + await().atMost(10, SECONDS).until { + productListener.messageLengths.size() == 2 } + then: + productListener.messageLengths.size() == 2 + productListener.messageLengths.contains(12) + productListener.messageLengths.contains(13) } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.groovy index 0fa692ffc..c09f5706a 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.groovy @@ -1,28 +1,34 @@ package io.micronaut.rabbitmq.docs.properties -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class PropertiesSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await - void "test sending and receiving properties"() { - startContext() +@MicronautTest +@Property(name = "spec.name", value = "PropertiesSpec") +class PropertiesSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener + void "test sending and receiving properties"() { when: // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient) productClient.send("body".bytes) productClient.send("guest", "text/html", "body2".bytes) productClient.send("guest", null, "body3".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.messageProperties.size() == 3 + } then: - waitFor { - assert productListener.messageProperties.size() == 3 - assert productListener.messageProperties.contains("guest|application/json|myApp") - assert productListener.messageProperties.contains("guest|text/html|myApp") - assert productListener.messageProperties.contains("guest|null|myApp") - } + productListener.messageProperties.contains("guest|application/json|myApp") + productListener.messageProperties.contains("guest|text/html|myApp") + productListener.messageProperties.contains("guest|null|myApp") } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.groovy index f91b79599..a394b866e 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.groovy @@ -1,24 +1,30 @@ package io.micronaut.rabbitmq.docs.publisher.acknowledge -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject import org.reactivestreams.Publisher import org.reactivestreams.Subscriber import org.reactivestreams.Subscription +import spock.lang.Specification import java.util.concurrent.CompletableFuture import java.util.concurrent.atomic.AtomicInteger -class PublisherAcknowledgeSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await +@MicronautTest +@Property(name = "spec.name", value = "PublisherAcknowledgeSpec") +class PublisherAcknowledgeSpec extends Specification { + @Inject ProductClient productClient void "test publisher acknowledgement"() { given: - startContext() AtomicInteger successCount = new AtomicInteger(0) AtomicInteger errorCount = new AtomicInteger(0) when: // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient) Publisher publisher = productClient.sendPublisher("publisher body".bytes) CompletableFuture future = productClient.sendFuture("future body".bytes) @@ -54,11 +60,12 @@ class PublisherAcknowledgeSpec extends AbstractRabbitMQTest { } } // end::producer[] + await().atMost(10, SECONDS).until { + successCount.get() == 2 + } then: - waitFor { - assert errorCount.get() == 0 - assert successCount.get() == 2 - } + errorCount.get() == 0 + successCount.get() == 2 } } diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.groovy index 6e1aab365..9363584de 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.groovy @@ -1,25 +1,33 @@ package io.micronaut.rabbitmq.docs.quickstart -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class QuickstartSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await - void "test product client and listener"() { - startContext() +@MicronautTest +@Property(name = "spec.name", value = "QuickstartSpec") +class QuickstartSpec extends Specification { + @Inject ProductClient productClient + @Inject ProductListener productListener + + void "test product client and listener"() { when: // tag::producer[] -def productClient = applicationContext.getBean(ProductClient) productClient.send("quickstart".bytes) // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + productListener.messageLengths.size() == 1 + } then: - waitFor { - assert productListener.messageLengths.size() == 1 - assert productListener.messageLengths[0] == "quickstart" - } + productListener.messageLengths.size() == 1 + productListener.messageLengths[0] == "quickstart" cleanup: // Finding that the context is closing the channel before ack is sent diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.groovy index 44330056a..060d51d17 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.groovy @@ -1,18 +1,19 @@ package io.micronaut.rabbitmq.docs.rpc -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject import reactor.core.publisher.Mono +import spock.lang.Specification -class RpcUppercaseSpec extends AbstractRabbitMQTest { +@MicronautTest +@Property(name = "spec.name", value = "RpcUppercaseSpec") +class RpcUppercaseSpec extends Specification { + @Inject ProductClient productClient void "test product client and listener"() { - startContext() - - when: // tag::producer[] - def productClient = applicationContext.getBean(ProductClient) - - then: + expect: productClient.send("hello") == "HELLO" Mono.from(productClient.sendReactive("world")).block() == "WORLD" // end::producer[] diff --git a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.groovy b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.groovy index 923c722f5..716bb110a 100644 --- a/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.groovy +++ b/docs-examples/example-groovy/src/test/groovy/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.groovy @@ -1,28 +1,38 @@ package io.micronaut.rabbitmq.docs.serdes -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.spock.annotation.MicronautTest +import jakarta.inject.Inject +import spock.lang.Specification -class ProductInfoSerDesSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS +import static org.awaitility.Awaitility.await + +@MicronautTest +@Property(name = "spec.name", value = "ProductInfoSerDesSpec") +class ProductInfoSerDesSpec extends Specification { + @Inject + ProductClient productClient + @Inject + ProductListener listener void "test using a custom serdes"() { - startContext() when: // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient) productClient.send(new ProductInfo("small", 10L, true)) productClient.send(new ProductInfo("medium", 20L, true)) productClient.send(new ProductInfo(null, 30L, false)) // end::producer[] - ProductListener listener = applicationContext.getBean(ProductListener) + await().atMost(10, SECONDS).until { + listener.messages.size() == 3 + } then: - waitFor { - assert listener.messages.size() == 3 - assert listener.messages.find({ p -> p.size == "small" && p.count == 10L && p.sealed }) != null - assert listener.messages.find({ p -> p.size == "medium" && p.count == 20L && p.sealed }) != null - assert listener.messages.find({ p -> p.size == null && p.count == 30L && !p.sealed }) != null - } + listener.messages.size() == 3 + listener.messages.find({ p -> p.size == "small" && p.count == 10L && p.sealed }) != null + listener.messages.find({ p -> p.size == "medium" && p.count == 20L && p.sealed }) != null + listener.messages.find({ p -> p.size == null && p.count == 30L && !p.sealed }) != null } } diff --git a/docs-examples/example-java/build.gradle b/docs-examples/example-java/build.gradle index 875f39622..ff2fb965e 100644 --- a/docs-examples/example-java/build.gradle +++ b/docs-examples/example-java/build.gradle @@ -1,13 +1,5 @@ plugins { - id 'io.micronaut.build.internal.rabbitmq-examples' + id 'io.micronaut.build.internal.rabbitmq-native-tests' } -dependencies { - testAnnotationProcessor mn.micronaut.inject.java - testImplementation libs.awaitility - testImplementation mnTest.micronaut.test.junit5 - testImplementation libs.junit.jupiter.engine -} -compileJava.options.compilerArgs += '-parameters' -compileTestJava.options.compilerArgs += '-parameters' diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/AbstractRabbitMQTest.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/AbstractRabbitMQTest.java deleted file mode 100644 index 88c88a261..000000000 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/AbstractRabbitMQTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package io.micronaut.rabbitmq; - -import io.micronaut.context.ApplicationContext; -import org.junit.jupiter.api.AfterEach; -import org.testcontainers.containers.GenericContainer; -import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy; - -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.Callable; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.awaitility.Awaitility.await; - -public abstract class AbstractRabbitMQTest { - - protected static GenericContainer rabbitContainer = new GenericContainer<>("library/rabbitmq:3.7") - .withExposedPorts(5672) - .waitingFor(new LogMessageWaitStrategy().withRegEx("(?s).*Server startup complete.*")); - - protected ApplicationContext applicationContext; - - protected void startContext() { - applicationContext = ApplicationContext.run(getConfiguration(), "test"); - } - - protected Map getConfiguration() { - rabbitContainer.start(); - - Map config = new HashMap<>(); - config.put("rabbitmq.port", rabbitContainer.getMappedPort(5672)); - config.put("spec.name", getClass().getSimpleName()); - return config; - } - - protected void waitFor(Callable conditionEvaluator) { - await().atMost(5, SECONDS).until(conditionEvaluator); - } - - @AfterEach - void cleanup() { - rabbitContainer.stop(); - - if (applicationContext != null) { - applicationContext.close(); - } - } -} diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.java index 165066b89..1a0b2a1c2 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.java @@ -1,25 +1,27 @@ package io.micronaut.rabbitmq.docs.consumer.acknowledge.type; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class AcknowledgeSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + +@MicronautTest +@Property(name = "spec.name", value = "AcknowledgeSpec") +class AcknowledgeSpec { @Test - void testAckingWithAcknowledgement() { - startContext(); + void testAckingWithAcknowledgement(ProductClient productClient, ProductListener productListener) { // tag::producer[] -ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("message body".getBytes()); productClient.send("message body".getBytes()); productClient.send("message body".getBytes()); productClient.send("message body".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messageCount.get() == 5 // the first message is rejected and re-queued ); } diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.java index 4135b3f04..51ed8f75c 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.java @@ -1,21 +1,24 @@ package io.micronaut.rabbitmq.docs.consumer.concurrent; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class ConcurrentSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + +@MicronautTest +@Property(name = "spec.name", value = "ConcurrentSpec") +class ConcurrentSpec { @Test - void testConcurrentConsumers() { - startContext(); + void testConcurrentConsumers(ProductClient productClient, ProductListener productListener) { - ProductClient productClient = applicationContext.getBean(ProductClient.class); for (int i = 0; i < 4; i++) { productClient.send("body".getBytes()); } - ProductListener productListener = applicationContext.getBean(ProductListener.class); - waitFor(() -> productListener.threads.size() == 4); + await().atMost(60, SECONDS).until(() -> productListener.threads.size() == 4); } } diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.java index 7df78d01e..925e2f732 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.java @@ -1,32 +1,43 @@ package io.micronaut.rabbitmq.docs.consumer.connection; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import java.net.URI; +import java.util.Collections; +import java.util.Map; + +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import io.micronaut.test.support.TestPropertyProvider; +import io.micronaut.testresources.client.TestResourcesClientFactory; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; -import java.util.Map; +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; -public class ConnectionSpec extends AbstractRabbitMQTest { +@MicronautTest +@Property(name = "spec.name", value = "ConnectionSpec") +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +class ConnectionSpec implements TestPropertyProvider { @Test - void testProductClientAndListener() { - startContext(); + void testProductClientAndListener(ProductClient productClient, ProductListener productListener) { // tag::producer[] -ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("connection-test".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - - waitFor(() -> + await().atMost(10, SECONDS).until(() -> productListener.messageLengths.size() == 1 && productListener.messageLengths.get(0).equals("connection-test") ); } - protected Map getConfiguration() { - Map config = super.getConfiguration(); - config.put("rabbitmq.servers.product-cluster.port", config.remove("rabbitmq.port")); - return config; + @Override + public Map getProperties() { + var client = TestResourcesClientFactory.fromSystemProperties().get(); + var rabbitURI = client.resolve("rabbitmq.uri", Map.of(), Map.of()); + return rabbitURI + .map(uri -> Map.of("rabbitmq.servers.product-cluster.port", String.valueOf(URI.create(uri).getPort()))) + .orElse(Collections.emptyMap()); } } diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.java index 0576ac7c7..e394e0dda 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.java @@ -1,23 +1,25 @@ package io.micronaut.rabbitmq.docs.consumer.custom.annotation; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class DeliveryTagSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testUsingACustomAnnotationBinder() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "DeliveryTagSpec") +class DeliveryTagSpec { + @Test + void testUsingACustomAnnotationBinder(ProductClient productClient, ProductListener productListener) { // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("body".getBytes()); productClient.send("body2".getBytes()); productClient.send("body3".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - waitFor(() -> productListener.messages.size() == 3); + await().atMost(60, SECONDS).until(() -> productListener.messages.size() == 3); } } diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.java index eddc97368..e404ff9a9 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.java @@ -1,24 +1,26 @@ package io.micronaut.rabbitmq.docs.consumer.custom.type; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class ProductInfoSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testUsingACustomTypeBinder() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "ProductInfoSpec") +class ProductInfoSpec { + @Test + void testUsingACustomTypeBinder(ProductClient productClient, ProductListener productListener) { // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("body".getBytes()); productClient.send("medium", 20L, "body2".getBytes()); productClient.send(null, 30L, "body3".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messages.size() == 3 && productListener.messages.stream().anyMatch(pi -> pi.getCount() == 10L) && productListener.messages.stream().anyMatch(pi -> pi.getCount() == 20L) && diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.java index 321c45244..1e966722e 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.java @@ -1,32 +1,31 @@ package io.micronaut.rabbitmq.docs.consumer.executor; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; +import io.micronaut.test.support.TestPropertyProvider; import org.junit.jupiter.api.Test; +import java.util.HashMap; import java.util.Map; -class CustomExecutorSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + +@MicronautTest(rebuildContext = true) +@Property(name = "spec.name", value = "CustomExecutorSpec") +@Property(name = "micronaut.executors.product-listener.type", value = "FIXED") +class CustomExecutorSpec { @Test - void testProductClientAndListener() { - startContext(); + void testProductClientAndListener(ProductClient productClient, ProductListener productListener) { // tag::producer[] -ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("custom-executor-test".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messageLengths.size() == 1 && productListener.messageLengths.get(0).equals("custom-executor-test") ); } - - protected Map getConfiguration() { - Map config = super.getConfiguration(); - config.put("micronaut.executors.product-listener.type", "FIXED"); - return config; - } } diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.java index 5a864e1d3..3955497d4 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.java @@ -1,24 +1,27 @@ package io.micronaut.rabbitmq.docs.consumer.types; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class TypeBindingSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + +@MicronautTest +@Property(name = "spec.name", value = "TypeBindingSpec") +class TypeBindingSpec { @Test - void testBindingByType() { - startContext(); + void testBindingByType(ProductClient productClient, ProductListener productListener) { // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("body".getBytes(), "text/html"); productClient.send("body2".getBytes(), "application/json"); productClient.send("body3".getBytes(), "text/xml"); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messages.size() == 3 && productListener.messages.contains("exchange: [], routingKey: [product], contentType: [text/html]") && productListener.messages.contains("exchange: [], routingKey: [product], contentType: [application/json]") && diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.java index 602b6fea8..d9005afa8 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.java @@ -1,23 +1,25 @@ package io.micronaut.rabbitmq.docs.exchange; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class CustomExchangeSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testUsingACustomExchange() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "CustomExchangeSpec") +class CustomExchangeSpec { - AnimalClient client = applicationContext.getBean(AnimalClient.class); - AnimalListener listener = applicationContext.getBean(AnimalListener.class); + @Test + void testUsingACustomExchange(AnimalClient client, AnimalListener listener) { client.send(new Cat("Whiskers", 9)); client.send(new Cat("Mr. Bigglesworth", 8)); client.send(new Snake("Buttercup", false)); client.send(new Snake("Monty the Python", true)); - waitFor(() -> + await().atMost(60, SECONDS).until(() -> listener.receivedAnimals.size() == 4 && listener.receivedAnimals.stream() .filter(Cat.class::isInstance) diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/headers/HeadersSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/headers/HeadersSpec.java index dac0741ad..107676aad 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/headers/HeadersSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/headers/HeadersSpec.java @@ -1,19 +1,22 @@ package io.micronaut.rabbitmq.docs.headers; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; import java.util.HashMap; import java.util.Map; -public class HeadersSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testPublishingAndReceivingHeaders() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "HeadersSpec") +class HeadersSpec { + @Test + void testPublishingAndReceivingHeaders(ProductClient productClient, ProductListener productListener) { // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("body".getBytes()); productClient.send("medium", 20L, "body2".getBytes()); productClient.send(null, 30L, "body3".getBytes()); @@ -24,9 +27,7 @@ void testPublishingAndReceivingHeaders() { productClient.send(headers, "body4".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messageProperties.size() == 4 && productListener.messageProperties.contains("true|10|small") && productListener.messageProperties.contains("true|20|medium") && diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/parameters/BindingSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/parameters/BindingSpec.java index dc7639359..114accdea 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/parameters/BindingSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/parameters/BindingSpec.java @@ -1,23 +1,25 @@ package io.micronaut.rabbitmq.docs.parameters; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class BindingSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testDynamicBinding() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "BindingSpec") +class BindingSpec { + @Test + void testDynamicBinding(ProductClient productClient, ProductListener productListener) { // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("message body".getBytes()); productClient.send("product", "message body2".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messageLengths.size() == 2 && productListener.messageLengths.contains(12) && productListener.messageLengths.contains(13) diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.java index 3dbb7e58b..d4ef384c0 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.java @@ -1,24 +1,26 @@ package io.micronaut.rabbitmq.docs.properties; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class PropertiesSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testPublishingAndReceivingProperties() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "PropertiesSpec") +class PropertiesSpec { + @Test + void testPublishingAndReceivingProperties(ProductClient productClient, ProductListener productListener) { // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("body".getBytes()); productClient.send("guest", "text/html", "body2".getBytes()); productClient.send("guest", null, "body3".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messageProperties.size() == 3 && productListener.messageProperties.contains("guest|application/json|myApp") && productListener.messageProperties.contains("guest|text/html|myApp") && diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.java index 601bba061..914c4792f 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.java @@ -1,6 +1,7 @@ package io.micronaut.rabbitmq.docs.publisher.acknowledge; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; import org.reactivestreams.Publisher; import org.reactivestreams.Subscriber; @@ -9,17 +10,20 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicInteger; -public class PublisherAcknowledgeSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; + +@MicronautTest +@Property(name = "spec.name", value = "PublisherAcknowledgeSpec") +class PublisherAcknowledgeSpec { @Test - void testPublisherAcknowledgement() { - startContext(); + void testPublisherAcknowledgement(ProductClient productClient) { AtomicInteger successCount = new AtomicInteger(0); AtomicInteger errorCount = new AtomicInteger(0); // tag::producer[] -ProductClient productClient = applicationContext.getBean(ProductClient.class); Publisher publisher = productClient.sendPublisher("publisher body".getBytes()); CompletableFuture future = productClient.sendFuture("future body".getBytes()); @@ -54,7 +58,7 @@ public void onComplete() { }); // end::producer[] - waitFor(() -> + await().atMost(60, SECONDS).until(() -> errorCount.get() == 0 && successCount.get() == 2 ); diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.java index ec994b2b0..e5db6e574 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.java @@ -1,22 +1,23 @@ package io.micronaut.rabbitmq.docs.quickstart; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class QuickstartSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testProductClientAndListener() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "QuickstartSpec") +class QuickstartSpec { + @Test + void testProductClientAndListener(ProductClient productClient, ProductListener productListener) { // tag::producer[] -ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send("quickstart".getBytes()); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messageLengths.size() == 1 && productListener.messageLengths.get(0).equals("quickstart") ); diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.java index 3aaf07948..131db7b3a 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.java @@ -1,19 +1,19 @@ package io.micronaut.rabbitmq.docs.rpc; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; import reactor.core.publisher.Mono; import static org.junit.jupiter.api.Assertions.assertEquals; -public class RpcUppercaseSpec extends AbstractRabbitMQTest { +@MicronautTest +@Property(name = "spec.name", value = "RpcUppercaseSpec") +class RpcUppercaseSpec { @Test - void testProductClientAndListener() { - startContext(); - + void testProductClientAndListener(ProductClient productClient) { // tag::producer[] -ProductClient productClient = applicationContext.getBean(ProductClient.class); assertEquals("RPC", productClient.send("rpc")); assertEquals("HELLO", Mono.from(productClient.sendReactive("hello")).block()); // end::producer[] diff --git a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.java b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.java index 24b1cd740..23d8009e9 100644 --- a/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.java +++ b/docs-examples/example-java/src/test/java/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.java @@ -1,24 +1,26 @@ package io.micronaut.rabbitmq.docs.serdes; -import io.micronaut.rabbitmq.AbstractRabbitMQTest; +import io.micronaut.context.annotation.Property; +import io.micronaut.test.extensions.junit5.annotation.MicronautTest; import org.junit.jupiter.api.Test; -public class ProductInfoSerDesSpec extends AbstractRabbitMQTest { +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.awaitility.Awaitility.await; - @Test - void testUsingACustomSerDes() { - startContext(); +@MicronautTest +@Property(name = "spec.name", value = "ProductInfoSerDesSpec") +class ProductInfoSerDesSpec { + @Test + void testUsingACustomSerDes(ProductClient productClient, ProductListener productListener) { // tag::producer[] - ProductClient productClient = applicationContext.getBean(ProductClient.class); productClient.send(new ProductInfo("small", 10L, true)); productClient.send(new ProductInfo("medium", 20L, true)); productClient.send(new ProductInfo(null, 30L, false)); // end::producer[] - ProductListener productListener = applicationContext.getBean(ProductListener.class); - waitFor(() -> + await().atMost(60, SECONDS).until(() -> productListener.messages.size() == 3 && productListener.messages.stream().anyMatch(pi -> pi.getCount() == 10L) && productListener.messages.stream().anyMatch(pi -> pi.getCount() == 20L) && diff --git a/docs-examples/example-kotlin/build.gradle b/docs-examples/example-kotlin/build.gradle index 2ea5e3db4..32d19b75e 100644 --- a/docs-examples/example-kotlin/build.gradle +++ b/docs-examples/example-kotlin/build.gradle @@ -1,27 +1,11 @@ plugins { id 'io.micronaut.build.internal.rabbitmq-examples' - alias libs.plugins.kotlin.jvm - alias libs.plugins.kotlin.kapt + id("org.jetbrains.kotlin.jvm") + id("org.jetbrains.kotlin.kapt") + id("org.jetbrains.kotlin.plugin.allopen") } -dependencies { - kaptTest enforcedPlatform("io.micronaut:micronaut-core-bom:$micronautVersion") - kaptTest mn.micronaut.inject.java - - testImplementation libs.kotest - testImplementation libs.kotlin.reflect - testImplementation libs.kotlin.stdlib -} - -test { - systemProperties['junit.jupiter.execution.parallel.enabled'] = true - maxParallelForks = Runtime.runtime.availableProcessors().intdiv(2) ?: 1 - forkEvery = 1 +micronaut { + testRuntime "kotest5" } -compileTestKotlin { - kotlinOptions { - jvmTarget = '17' - javaParameters = true - } -} diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/AbstractRabbitMQTest.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/AbstractRabbitMQTest.kt deleted file mode 100644 index e646237c1..000000000 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/AbstractRabbitMQTest.kt +++ /dev/null @@ -1,29 +0,0 @@ -package io.micronaut.rabbitmq - -import io.kotest.core.spec.style.BehaviorSpec -import io.micronaut.context.ApplicationContext -import org.testcontainers.containers.wait.strategy.LogMessageWaitStrategy - -abstract class AbstractRabbitMQTest(body: BehaviorSpec.() -> Unit): BehaviorSpec(body) { - - companion object { - val rabbitContainer = KGenericContainer("library/rabbitmq:3.7") - .withExposedPorts(5672) - .waitingFor(LogMessageWaitStrategy().withRegEx("(?s).*Server startup complete.*"))!! - - init { - rabbitContainer.start() - } - - fun startContext(specName: String): ApplicationContext = - ApplicationContext.run(getDefaultConfig(specName), "test") - - fun startContext(configuration: Map): ApplicationContext = - ApplicationContext.run(configuration, "test") - - fun getDefaultConfig(specName: String): MutableMap = - mutableMapOf( - "rabbitmq.port" to rabbitContainer.getMappedPort(5672), - "spec.name" to specName) - } -} diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/KGenericContainer.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/KGenericContainer.kt deleted file mode 100644 index 945177088..000000000 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/KGenericContainer.kt +++ /dev/null @@ -1,5 +0,0 @@ -package io.micronaut.rabbitmq - -import org.testcontainers.containers.GenericContainer - -class KGenericContainer(imageName: String) : GenericContainer(imageName) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/ProjectConfig.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/ProjectConfig.kt new file mode 100644 index 000000000..6a9348d98 --- /dev/null +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/ProjectConfig.kt @@ -0,0 +1,11 @@ +package io.micronaut.rabbitmq.docs + + +import io.kotest.core.config.AbstractProjectConfig +import io.micronaut.test.extensions.kotest5.MicronautKotest5Extension + +@Suppress("unused") +object ProjectConfig : AbstractProjectConfig() { + override fun extensions() = listOf(MicronautKotest5Extension) +} + diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.kt index 7adc8b728..66b8bb67c 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/acknowledge/type/AcknowledgeSpec.kt @@ -1,24 +1,22 @@ package io.micronaut.rabbitmq.docs.consumer.acknowledge.type import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class AcknowledgeSpec : AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "AcknowledgeSpec") +class AcknowledgeSpec(productClient: ProductClient, productListener: ProductListener) : BehaviorSpec({ val specName = javaClass.simpleName given("An acknowledgement argument") { - val ctx = startContext(specName) - `when`("The messages are published") { - val productListener = ctx.getBean(ProductListener::class.java) // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send("body".toByteArray()) productClient.send("body".toByteArray()) productClient.send("body".toByteArray()) @@ -26,12 +24,10 @@ class AcknowledgeSpec : AbstractRabbitMQTest({ // end::producer[] then("The messages are received") { - eventually(10.seconds) { + eventually(10.seconds) { productListener.messageCount.get() shouldBe 5 } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.kt index 985a753d9..34413e3be 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/concurrent/ConcurrentSpec.kt @@ -1,22 +1,20 @@ package io.micronaut.rabbitmq.docs.consumer.concurrent +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.framework.concurrency.eventually import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class ConcurrentSpec : AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "ConcurrentSpec") +class ConcurrentSpec(productClient: ProductClient, productListener: ProductListener) : BehaviorSpec({ val specName = javaClass.simpleName given("A basic producer and consumer") { - val ctx = startContext(specName) - `when`("The messages are published") { - val productListener = ctx.getBean(ProductListener::class.java) - val productClient = ctx.getBean(ProductClient::class.java) for (i in 0..3) { productClient.send("body".toByteArray()) } @@ -27,7 +25,5 @@ class ConcurrentSpec : AbstractRabbitMQTest({ } } } - - ctx.close() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.kt index ec4d921cb..5001099e6 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/connection/ConnectionSpec.kt @@ -1,39 +1,47 @@ package io.micronaut.rabbitmq.docs.consumer.connection import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.AnnotationSpec import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest +import io.micronaut.test.support.TestPropertyProvider +import io.micronaut.testresources.client.TestResourcesClientFactory +import jakarta.inject.Inject +import java.net.URI +import java.util.Map import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime - -@OptIn(ExperimentalTime::class) -class ConnectionSpec : AbstractRabbitMQTest({ - - val specName = javaClass.simpleName - - given("A basic producer and consumer") { - val config = AbstractRabbitMQTest.getDefaultConfig(specName) - config["rabbitmq.servers.product-cluster.port"] = config.remove("rabbitmq.port")!! - - val ctx = startContext(config) - - `when`("the message is published") { - val productListener = ctx.getBean(ProductListener::class.java) +@MicronautTest +@Property(name = "spec.name", value = "ConnectionSpec") +class ConnectionSpec + : TestPropertyProvider, AnnotationSpec() { + @Inject + lateinit var productClient: ProductClient + @Inject + lateinit var productListener: ProductListener + + @Test + suspend fun testBasicProducerAndConsumer() { // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) - productClient.send("connection-test".toByteArray()) + productClient.send("connection-test".toByteArray()) // end::producer[] - - then("the message is consumed") { - eventually(10.seconds) { - productListener.messageLengths.size shouldBe 1 - productListener.messageLengths[0] shouldBe "connection-test" - } - } + eventually(10.seconds) { + productListener.messageLengths.size shouldBe 1 + productListener.messageLengths[0] shouldBe "connection-test" } + } - Thread.sleep(200) - ctx.stop() + override fun getProperties(): MutableMap { + val client = TestResourcesClientFactory.fromSystemProperties().get() + val rabbitURI = client.resolve("rabbitmq.uri", Map.of(), Map.of()) + return rabbitURI + .map { uri: String -> + Map.of( + "rabbitmq.servers.product-cluster.port", + URI.create(uri).port.toString() + ) + } + .orElse(emptyMap()) } -}) +} diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.kt index 7118c6b3d..7eaa2c03c 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/annotation/DeliveryTagSpec.kt @@ -1,24 +1,23 @@ package io.micronaut.rabbitmq.docs.consumer.custom.annotation import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class DeliveryTagSpec : AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "DeliveryTagSpec") +class DeliveryTagSpec(productClient: ProductClient, productListener: ProductListener) : BehaviorSpec({ val specName = javaClass.simpleName given("Using a custom annotation binder") { - val ctx = startContext(specName) `when`("The messages are published") { - val productListener = ctx.getBean(ProductListener::class.java) - // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send("body".toByteArray()) productClient.send("body2".toByteArray()) productClient.send("body3".toByteArray()) @@ -30,7 +29,5 @@ class DeliveryTagSpec : AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.kt index 758b96457..de1816c71 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/custom/type/ProductInfoSpec.kt @@ -1,25 +1,24 @@ package io.micronaut.rabbitmq.docs.consumer.custom.type import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldExist import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class ProductInfoSpec : AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "ProductInfoSpec") +class ProductInfoSpec(productClient: ProductClient, productListener: ProductListener) : BehaviorSpec({ val specName = javaClass.simpleName given("A custom type binder") { - val ctx = startContext(specName) - `when`("The messages are published") { - val productListener = ctx.getBean(ProductListener::class.java) // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send("body".toByteArray()) productClient.send("medium", 20L, "body2".toByteArray()) productClient.send(null, 30L, "body3".toByteArray()) @@ -34,7 +33,5 @@ class ProductInfoSpec : AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.kt index 3f48da033..bbb0be2f6 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/executor/CustomExecutorSpec.kt @@ -1,38 +1,35 @@ package io.micronaut.rabbitmq.docs.consumer.executor import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.AnnotationSpec +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest +import jakarta.inject.Inject import kotlin.time.Duration.Companion.seconds -class CustomExecutorSpec : AbstractRabbitMQTest({ +@MicronautTest(rebuildContext = true) +@Property(name = "micronaut.executors.product-listener.type", value = "FIXED") +@Property(name = "spec.name", value = "CustomExecutorSpec") +class CustomExecutorSpec : AnnotationSpec() { + @Inject + lateinit var productClient: ProductClient - val specName = javaClass.simpleName + @Inject + lateinit var productListener: ProductListener - given("A basic producer and consumer") { - val config = AbstractRabbitMQTest.getDefaultConfig(specName) - config["micronaut.executors.product-listener.type"] = "FIXED" + @Test + suspend fun testBasicConsumerAndProducer() { - val ctx = startContext(config) - - `when`("the message is published") { - val productListener = ctx.getBean(ProductListener::class.java) // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) - productClient.send("custom-executor-test".toByteArray()) + productClient.send("custom-executor-test".toByteArray()) // end::producer[] - then("the message is consumed") { - eventually(10.seconds) { - productListener.messageLengths.size shouldBe 1 - productListener.messageLengths[0] shouldBe "custom-executor-test" - } - } + eventually(10.seconds) { + productListener.messageLengths.size shouldBe 1 + productListener.messageLengths[0] shouldBe "custom-executor-test" } - - rabbitContainer.stop() - - ctx.stop() } -}) +} diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.kt index 7f431fa70..70ef68046 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/consumer/types/TypeBindingSpec.kt @@ -1,25 +1,25 @@ package io.micronaut.rabbitmq.docs.consumer.types import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class TypeBindingSpec : AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "TypeBindingSpec") +class TypeBindingSpec(productClient: ProductClient, productListener: ProductListener) : BehaviorSpec({ val specName = javaClass.simpleName given("A basic producer and consumer") { - val ctx = startContext(specName) `when`("The messages are published") { - val productListener = ctx.getBean(ProductListener::class.java) // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send("body".toByteArray(), "text/html") productClient.send("body2".toByteArray(), "application/json") productClient.send("body3".toByteArray(), "text/xml") @@ -34,7 +34,5 @@ class TypeBindingSpec : AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.kt index 1b060a882..39071afbf 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/exchange/CustomExchangeSpec.kt @@ -1,23 +1,21 @@ package io.micronaut.rabbitmq.docs.exchange import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldExist import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class CustomExchangeSpec: AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "CustomExchangeSpec") +class CustomExchangeSpec(client: AnimalClient, listener: AnimalListener): BehaviorSpec({ val specName = javaClass.simpleName given("Using a custom exchange") { - val ctx = startContext(specName) - - val client = ctx.getBean(AnimalClient::class.java) - val listener = ctx.getBean(AnimalListener::class.java) - `when`("the messages are published") { client.send(Cat("Whiskers", 9)) client.send(Cat("Mr. Bigglesworth", 8)) @@ -43,7 +41,5 @@ class CustomExchangeSpec: AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/headers/HeadersSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/headers/HeadersSpec.kt index d0bb3a452..c7f97d43d 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/headers/HeadersSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/headers/HeadersSpec.kt @@ -1,25 +1,22 @@ package io.micronaut.rabbitmq.docs.headers import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class HeadersSpec : AbstractRabbitMQTest({ - - val specName = javaClass.simpleName +@MicronautTest +@Property(name = "spec.name", value = "HeadersSpec") +class HeadersSpec(productClient: ProductClient, productListener: ProductListener) : BehaviorSpec({ given("A basic producer and consumer") { - val ctx = startContext(specName) - `when`("The messages are published") { - val productListener = ctx.getBean(ProductListener::class.java) // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send("body".toByteArray()) productClient.send("medium", 20L, "body2".toByteArray()) productClient.send(null, 30L, "body3".toByteArray()) @@ -36,7 +33,5 @@ class HeadersSpec : AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/parameters/BindingSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/parameters/BindingSpec.kt index 7d1ad3c9e..4bd7b8b0c 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/parameters/BindingSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/parameters/BindingSpec.kt @@ -1,25 +1,22 @@ package io.micronaut.rabbitmq.docs.parameters import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class BindingSpec: AbstractRabbitMQTest({ - - val specName = javaClass.simpleName +@MicronautTest +@Property(name = "spec.name", value = "BindingSpec") +class BindingSpec(productClient: ProductClient, productListener: ProductListener): BehaviorSpec({ given("A basic producer and consumer") { - val ctx = startContext(specName) - `when`("The messages are published") { - val productListener = ctx.getBean(ProductListener::class.java) // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send("message body".toByteArray()) productClient.send("product", "message body2".toByteArray()) // end::producer[] @@ -32,7 +29,5 @@ class BindingSpec: AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.kt index a896b7834..832df4192 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/properties/PropertiesSpec.kt @@ -1,30 +1,27 @@ package io.micronaut.rabbitmq.docs.properties import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldContain import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class PropertiesSpec : AbstractRabbitMQTest({ - - val specName = javaClass.simpleName +@MicronautTest +@Property(name = "spec.name", value = "PropertiesSpec") +class PropertiesSpec(productClient: ProductClient, productListener: ProductListener) : BehaviorSpec({ given("publishing and receiving properties") { - val ctx = startContext(specName) - `when`("messages with properties are sent") { // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send("body".toByteArray()) productClient.send("guest", "text/html", "body2".toByteArray()) productClient.send("guest", null, "body3".toByteArray()) // end::producer[] then("the messages are received") { - val productListener = ctx.getBean(ProductListener::class.java) eventually(10.seconds) { productListener.messageProperties.size shouldBe 3 @@ -34,7 +31,5 @@ class PropertiesSpec : AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.kt index 2a81001d0..677faf869 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/publisher/acknowledge/PublisherAcknowledgeSpec.kt @@ -1,28 +1,26 @@ package io.micronaut.rabbitmq.docs.publisher.acknowledge; import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlinx.coroutines.async import org.reactivestreams.Subscriber import org.reactivestreams.Subscription import java.util.concurrent.atomic.AtomicInteger import kotlin.time.Duration.Companion.seconds -import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class PublisherAcknowledgeSpec : AbstractRabbitMQTest({ - - val specName = javaClass.simpleName +@MicronautTest +@Property(name = "spec.name", value = "PublisherAcknowledgeSpec") +class PublisherAcknowledgeSpec(productClient: ProductClient) : BehaviorSpec({ given("Publisher acknowledgement") { - val ctx = startContext(specName) val successCount = AtomicInteger(0) val errorCount = AtomicInteger(0) `when`("The messages are published") { // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) val publisher = productClient.sendPublisher("publisher body".toByteArray()) val future = productClient.sendFuture("future body".toByteArray()) val deferred = async { @@ -70,7 +68,5 @@ class PublisherAcknowledgeSpec : AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.kt index 5f6687b70..b78a4af60 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/quickstart/QuickstartSpec.kt @@ -1,24 +1,21 @@ package io.micronaut.rabbitmq.docs.quickstart import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class QuickstartSpec: AbstractRabbitMQTest({ - - val specName = javaClass.simpleName +@MicronautTest +@Property(name = "spec.name", value = "QuickstartSpec") +class QuickstartSpec(productClient: ProductClient, productListener: ProductListener): BehaviorSpec({ given("A basic producer and consumer") { - val ctx = startContext(specName) - `when`("the message is published") { - val productListener = ctx.getBean(ProductListener::class.java) // tag::producer[] -val productClient = ctx.getBean(ProductClient::class.java) productClient.send("quickstart".toByteArray()) // end::producer[] @@ -29,8 +26,5 @@ productClient.send("quickstart".toByteArray()) } } } - - Thread.sleep(1000) - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.kt index 22a22dfef..1a58cc86c 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/rpc/RpcUppercaseSpec.kt @@ -1,28 +1,24 @@ package io.micronaut.rabbitmq.docs.rpc +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import reactor.core.publisher.Mono import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class RpcUppercaseSpec: AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "RpcUppercaseSpec") +class RpcUppercaseSpec(productClient: ProductClient): BehaviorSpec({ val specName = javaClass.simpleName given("A basic producer and consumer") { - val ctx = startContext(specName) - `when`("the message is published") { - - val productClient = ctx.getBean(ProductClient::class.java) - then("the message is consumed") { productClient.send("hello") shouldBe "HELLO" Mono.from(productClient.sendReactive("world")).block() shouldBe "WORLD" } } - - ctx.stop() } }) diff --git a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.kt b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.kt index 84223d2e8..1472a3e9a 100644 --- a/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.kt +++ b/docs-examples/example-kotlin/src/test/kotlin/io/micronaut/rabbitmq/docs/serdes/ProductInfoSerDesSpec.kt @@ -1,25 +1,24 @@ package io.micronaut.rabbitmq.docs.serdes import io.kotest.assertions.timing.eventually +import io.kotest.core.spec.style.BehaviorSpec import io.kotest.matchers.collections.shouldExist import io.kotest.matchers.shouldBe -import io.micronaut.rabbitmq.AbstractRabbitMQTest +import io.micronaut.context.annotation.Property +import io.micronaut.test.extensions.kotest5.annotation.MicronautTest import kotlin.time.Duration.Companion.seconds import kotlin.time.ExperimentalTime -@OptIn(ExperimentalTime::class) -class ProductInfoSerDesSpec: AbstractRabbitMQTest({ +@MicronautTest +@Property(name = "spec.name", value = "ProductInfoSerDesSpec") +class ProductInfoSerDesSpec(productClient: ProductClient, listener: ProductListener): BehaviorSpec({ val specName = javaClass.simpleName given("A basic producer and consumer") { - val ctx = startContext(specName) - `when`("the message is published") { - val listener = ctx.getBean(ProductListener::class.java) // tag::producer[] - val productClient = ctx.getBean(ProductClient::class.java) productClient.send(ProductInfo("small", 10L, true)) productClient.send(ProductInfo("medium", 20L, true)) productClient.send(ProductInfo(null, 30L, false)) @@ -34,7 +33,5 @@ class ProductInfoSerDesSpec: AbstractRabbitMQTest({ } } } - - ctx.stop() } }) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 2f178887b..b421ff915 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,7 +1,9 @@ [versions] micronaut-docs = '2.0.0' -micronaut = '4.0.0-M1' +micronaut = '4.0.0-M2' +micronaut-platform = '4.0.0-M1' micronaut-test = '4.0.0-M1' +micronaut-gradle-plugin = "4.0.0-M1" groovy = '4.0.10' spock = '2.3-groovy-4.0' @@ -34,7 +36,8 @@ testcontainers-spock = { module = 'org.testcontainers:spock', version.ref = 'tes micronaut-micrometer = { module = "io.micronaut.micrometer:micronaut-micrometer-bom", version.ref = "micronaut-micrometer" } micronaut-serde = { module = "io.micronaut.serde:micronaut-serde-bom", version.ref = "micronaut-serde" } +gradle-micronaut = { module = "io.micronaut.gradle:micronaut-gradle-plugin", version.ref = "micronaut-gradle-plugin" } +gradle-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } +gradle-kotlin-allopen = { module = "org.jetbrains.kotlin:kotlin-allopen", version.ref = "kotlin" } +gradle-kotlin-noarg = { module = "org.jetbrains.kotlin:kotlin-noarg", version.ref = "kotlin" } -[plugins] -kotlin-jvm = { id = 'org.jetbrains.kotlin.jvm', version.ref = 'kotlin' } -kotlin-kapt = { id = 'org.jetbrains.kotlin.kapt', version.ref = 'kotlin' } diff --git a/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitBinderRegistry.java b/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitBinderRegistry.java index 12b61d179..6d29cdc35 100644 --- a/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitBinderRegistry.java +++ b/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitBinderRegistry.java @@ -69,8 +69,7 @@ public RabbitBinderRegistry(RabbitDefaultBinder defaultBinder, } @Override - public Optional> findArgumentBinder(Argument argument, RabbitConsumerState source) { - + public Optional> findArgumentBinder(Argument argument) { Optional> opt = argument.getAnnotationMetadata().getAnnotationTypeByStereotype(Bindable.class); if (opt.isPresent()) { Class annotationType = opt.get(); diff --git a/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitMessageCloseable.java b/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitMessageCloseable.java index 859a06f12..658f8d753 100644 --- a/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitMessageCloseable.java +++ b/rabbitmq/src/main/java/io/micronaut/rabbitmq/bind/RabbitMessageCloseable.java @@ -58,6 +58,7 @@ public RabbitMessageCloseable(RabbitConsumerState consumerState, public void close() throws MessageAcknowledgementException { switch (acknowledgmentAction) { case NONE: + default: break; case ACK: try { diff --git a/rabbitmq/src/main/java/io/micronaut/rabbitmq/connect/RabbitConnectionFactory.java b/rabbitmq/src/main/java/io/micronaut/rabbitmq/connect/RabbitConnectionFactory.java index 7435e08a9..5920c40d5 100644 --- a/rabbitmq/src/main/java/io/micronaut/rabbitmq/connect/RabbitConnectionFactory.java +++ b/rabbitmq/src/main/java/io/micronaut/rabbitmq/connect/RabbitConnectionFactory.java @@ -15,21 +15,24 @@ */ package io.micronaut.rabbitmq.connect; +import java.io.IOException; +import java.util.List; +import java.util.Optional; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.TimeoutException; + import com.rabbitmq.client.Address; import com.rabbitmq.client.Connection; import io.micronaut.context.BeanContext; -import io.micronaut.context.annotation.Bean; import io.micronaut.context.annotation.EachBean; import io.micronaut.context.annotation.Factory; import io.micronaut.context.exceptions.BeanInstantiationException; import io.micronaut.inject.qualifiers.Qualifiers; +import jakarta.annotation.PreDestroy; import jakarta.inject.Singleton; - -import java.io.IOException; -import java.util.List; -import java.util.Optional; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.TimeoutException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A factory for creating a connection to RabbitMQ. @@ -39,13 +42,14 @@ */ @Factory public class RabbitConnectionFactory { + private static final Logger LOG = LoggerFactory.getLogger(RabbitConnectionFactory.class); + private final ConcurrentLinkedQueue activeConnections = new ConcurrentLinkedQueue<>(); /** * @param connectionFactory The factory to create the connection * @param beanContext The bean context to dynamically retrieve the executor service * @return The connection */ - @Bean(preDestroy = "close") @Singleton @EachBean(RabbitConnectionFactoryConfig.class) Connection connection(RabbitConnectionFactoryConfig connectionFactory, @@ -53,13 +57,41 @@ Connection connection(RabbitConnectionFactoryConfig connectionFactory, try { ExecutorService executorService = beanContext.getBean(ExecutorService.class, Qualifiers.byName(connectionFactory.getConsumerExecutor())); Optional> addresses = connectionFactory.getAddresses(); + Connection connection; if (addresses.isPresent()) { - return connectionFactory.newConnection(executorService, addresses.get()); + connection = connectionFactory.newConnection(executorService, addresses.get()); } else { - return connectionFactory.newConnection(executorService); + connection = connectionFactory.newConnection(executorService); } + activeConnections.add(new ActiveConnection(connection, connectionFactory)); + return connection; } catch (IOException | TimeoutException e) { throw new BeanInstantiationException("Error creating connection to RabbitMQ", e); } } + + /** + * Closes active connections. + */ + @PreDestroy + void shutdownConnections() { + try { + for (ActiveConnection activeConnection : activeConnections) { + Connection connection = activeConnection.connection(); + if (connection.isOpen()) { + try { + connection.close(activeConnection.connectionFactory().getShutdownTimeout()); + } catch (Exception e) { + LOG.warn("Error closing RabbitMQ connection: " + e.getMessage(), e); + } + } + } + } finally { + this.activeConnections.clear(); + } + } + + private record ActiveConnection(Connection connection, + RabbitConnectionFactoryConfig connectionFactory) { + } } diff --git a/rabbitmq/src/main/resources/META-INF/native-image/io.micronaut.rabbitmq/native-image.properties b/rabbitmq/src/main/resources/META-INF/native-image/io.micronaut.rabbitmq/native-image.properties deleted file mode 100644 index a80a2a73c..000000000 --- a/rabbitmq/src/main/resources/META-INF/native-image/io.micronaut.rabbitmq/native-image.properties +++ /dev/null @@ -1,2 +0,0 @@ -Args = --initialize-at-build-time=com.rabbitmq.client \ - --initialize-at-run-time=io.micronaut.rabbitmq.health.$RabbitMQHealthIndicatorDefinition