Create dedicated spring-boot-testcontainers module

Create a dedicated testcontainers module containing the service
connectors code.

Closes gh-34757
This commit is contained in:
Phillip Webb
2023-04-10 20:15:39 -07:00
parent 2951cc7594
commit 11dac5b5b7
103 changed files with 431 additions and 325 deletions

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testcontainers.service.connection;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnectionContextCustomizerFactoryTests.ServiceConnections.NestedClass;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* Tests for {@link ServiceConnectionContextCustomizerFactory}.
*
* @author Andy Wilkinson
*/
public class ServiceConnectionContextCustomizerFactoryTests {
private final ServiceConnectionContextCustomizerFactory factory = new ServiceConnectionContextCustomizerFactory();
@Test
void whenClassHasNoServiceConnectionsThenCreateReturnsNull() {
assertThat(this.factory.createContextCustomizer(NoServiceConnections.class, null)).isNull();
}
@Test
void whenClassHasServiceConnectionsThenCreateReturnsCustomizer() {
ServiceConnectionContextCustomizer customizer = (ServiceConnectionContextCustomizer) this.factory
.createContextCustomizer(ServiceConnections.class, null);
assertThat(customizer).isNotNull();
assertThat(customizer.getSources()).hasSize(2);
}
@Test
void whenEnclosingClassHasServiceConnectionsThenCreateReturnsCustomizer() {
ServiceConnectionContextCustomizer customizer = (ServiceConnectionContextCustomizer) this.factory
.createContextCustomizer(NestedClass.class, null);
assertThat(customizer).isNotNull();
assertThat(customizer.getSources()).hasSize(3);
}
@Test
void whenClassHasNonStaticServiceConnectionThenCreateShouldFailWithHelpfulIllegalStateException() {
assertThatIllegalStateException()
.isThrownBy(() -> this.factory.createContextCustomizer(NonStaticServiceConnection.class, null))
.withMessage("@ServiceConnection field 'service' must be static");
}
static class NoServiceConnections {
}
static class ServiceConnections {
@ServiceConnection(TestConnectionDetails.class)
private static GenericContainer<?> service1 = new GenericContainer<>("example");
@ServiceConnection(TestConnectionDetails.class)
private static GenericContainer<?> service2 = new GenericContainer<>("example");
@Nested
class NestedClass {
@ServiceConnection(TestConnectionDetails.class)
private static GenericContainer<?> service3 = new GenericContainer<>("example");
}
}
static class NonStaticServiceConnection {
@ServiceConnection(TestConnectionDetails.class)
private GenericContainer<?> service = new GenericContainer<>("example");
}
static class TestConnectionDetails implements ConnectionDetails {
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testcontainers.service.connection.amqp;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.RabbitMQContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link RabbitServiceConnection}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class RabbitServiceConnectionTests {
@Container
@RabbitServiceConnection
static final RabbitMQContainer rabbit = new RabbitMQContainer(DockerImageName.parse("rabbitmq:3.11-alpine"));
@Autowired(required = false)
private RabbitConnectionDetails connectionDetails;
@Autowired
private RabbitTemplate rabbitTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToRabbitContainer() {
assertThat(this.connectionDetails).isNotNull();
this.rabbitTemplate.convertAndSend("test", "message");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RabbitAutoConfiguration.class)
static class TestConfiguration {
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@RabbitListener(queuesToDeclare = @Queue("test"))
void processMessage(String message) {
this.messages.add(message);
}
}
}

View File

@@ -0,0 +1,66 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testcontainers.service.connection.influx;
import org.influxdb.InfluxDB;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.InfluxDBContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.influx.InfluxDbAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link InfluxDbServiceConnection}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class InfluxDbServiceConnectionTests {
private static final String INFLUXDB_VERSION = "2.6.1";
@Container
@InfluxDbServiceConnection
static final InfluxDBContainer<?> influxDbService = new InfluxDBContainer<>(
DockerImageName.parse("influxdb").withTag(INFLUXDB_VERSION));
@Autowired
private InfluxDB influxDb;
@Test
void connectionCanBeMadeToInfluxDbContainer() {
assertThat(this.influxDb.version()).isEqualTo("v" + INFLUXDB_VERSION);
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(InfluxDbAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testcontainers.service.connection.kafka;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.KafkaContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.DockerImageName;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.kafka.annotation.KafkaListener;
import org.springframework.kafka.core.KafkaTemplate;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link KafkaServiceConnection}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
@TestPropertySource(properties = { "spring.kafka.consumer.group-id=test-group",
"spring.kafka.consumer.auto-offset-reset=earliest" })
class KafkaServiceConnectionTests {
@Container
@KafkaServiceConnection
static final KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:5.4.3"));
@Autowired
private KafkaTemplate<String, String> kafkaTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToKafkaContainer() {
this.kafkaTemplate.send("test-topic", "test-data");
Awaitility.waitAtMost(Duration.ofMinutes(4))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("test-data"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(KafkaAutoConfiguration.class)
static class TestConfiguration {
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@KafkaListener(topics = "test-topic")
void processMessage(String message) {
this.messages.add(message);
}
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<include resource="org/springframework/boot/logging/logback/base.xml"/>
</configuration>