Update spring-boot-testcontainers to use docker-test plugin

See gh-41228
This commit is contained in:
Andy Wilkinson
2024-06-25 10:51:33 +01:00
parent d78c7b541a
commit 3f1f801461
32 changed files with 197 additions and 124 deletions

View File

@@ -0,0 +1,199 @@
/*
* Copyright 2012-2024 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;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.Container;
import org.testcontainers.containers.PostgreSQLContainer;
import org.springframework.boot.testcontainers.beans.TestcontainerBeanDefinition;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
/**
* Tests for {@link ImportTestcontainers}.
*
* @author Phillip Webb
*/
@DisabledIfDockerUnavailable
class ImportTestcontainersTests {
private AnnotationConfigApplicationContext applicationContext;
@AfterEach
void teardown() {
if (this.applicationContext != null) {
this.applicationContext.close();
}
}
@Test
void importWithoutValueRegistersBeans() {
this.applicationContext = new AnnotationConfigApplicationContext(ImportWithoutValue.class);
String[] beanNames = this.applicationContext.getBeanNamesForType(PostgreSQLContainer.class);
assertThat(beanNames).hasSize(1);
assertThat(this.applicationContext.getBean(beanNames[0])).isSameAs(ImportWithoutValue.container);
TestcontainerBeanDefinition beanDefinition = (TestcontainerBeanDefinition) this.applicationContext
.getBeanDefinition(beanNames[0]);
assertThat(beanDefinition.getContainerImageName()).isEqualTo(ImportWithoutValue.container.getDockerImageName());
assertThat(beanDefinition.getAnnotations().isPresent(ContainerAnnotation.class)).isTrue();
}
@Test
void importWithValueRegistersBeans() {
this.applicationContext = new AnnotationConfigApplicationContext(ImportWithValue.class);
String[] beanNames = this.applicationContext.getBeanNamesForType(PostgreSQLContainer.class);
assertThat(beanNames).hasSize(1);
assertThat(this.applicationContext.getBean(beanNames[0])).isSameAs(ContainerDefinitions.container);
TestcontainerBeanDefinition beanDefinition = (TestcontainerBeanDefinition) this.applicationContext
.getBeanDefinition(beanNames[0]);
assertThat(beanDefinition.getContainerImageName())
.isEqualTo(ContainerDefinitions.container.getDockerImageName());
assertThat(beanDefinition.getAnnotations().isPresent(ContainerAnnotation.class)).isTrue();
}
@Test
void importWhenHasNoContainerFieldsDoesNothing() {
this.applicationContext = new AnnotationConfigApplicationContext(NoContainers.class);
String[] beanNames = this.applicationContext.getBeanNamesForType(Container.class);
assertThat(beanNames).isEmpty();
}
@Test
void importWhenHasNullContainerFieldThrowsException() {
assertThatIllegalStateException()
.isThrownBy(() -> this.applicationContext = new AnnotationConfigApplicationContext(NullContainer.class))
.withMessage("Container field 'container' must not have a null value");
}
@Test
void importWhenHasNonStaticContainerFieldThrowsException() {
assertThatIllegalStateException()
.isThrownBy(
() -> this.applicationContext = new AnnotationConfigApplicationContext(NonStaticContainer.class))
.withMessage("Container field 'container' must be static");
}
@Test
void importWhenHasContainerDefinitionsWithDynamicPropertySource() {
this.applicationContext = new AnnotationConfigApplicationContext(
ContainerDefinitionsWithDynamicPropertySource.class);
assertThat(this.applicationContext.getEnvironment().containsProperty("container.port")).isTrue();
}
@Test
void importWhenHasNonStaticDynamicPropertySourceMethod() {
assertThatIllegalStateException()
.isThrownBy(() -> this.applicationContext = new AnnotationConfigApplicationContext(
NonStaticDynamicPropertySourceMethod.class))
.withMessage("@DynamicPropertySource method 'containerProperties' must be static");
}
@Test
void importWhenHasBadArgsDynamicPropertySourceMethod() {
assertThatIllegalStateException()
.isThrownBy(() -> this.applicationContext = new AnnotationConfigApplicationContext(
BadArgsDynamicPropertySourceMethod.class))
.withMessage("@DynamicPropertySource method 'containerProperties' must be static");
}
@ImportTestcontainers
static class ImportWithoutValue {
@ContainerAnnotation
static PostgreSQLContainer<?> container = TestImage.container(PostgreSQLContainer.class);
}
@ImportTestcontainers(ContainerDefinitions.class)
static class ImportWithValue {
}
@ImportTestcontainers
static class NoContainers {
}
@ImportTestcontainers
static class NullContainer {
static PostgreSQLContainer<?> container = null;
}
@ImportTestcontainers
static class NonStaticContainer {
PostgreSQLContainer<?> container = TestImage.container(PostgreSQLContainer.class);
}
interface ContainerDefinitions {
@ContainerAnnotation
PostgreSQLContainer<?> container = TestImage.container(PostgreSQLContainer.class);
}
@Retention(RetentionPolicy.RUNTIME)
@interface ContainerAnnotation {
}
@ImportTestcontainers
static class ContainerDefinitionsWithDynamicPropertySource {
static PostgreSQLContainer<?> container = TestImage.container(PostgreSQLContainer.class);
@DynamicPropertySource
static void containerProperties(DynamicPropertyRegistry registry) {
registry.add("container.port", container::getFirstMappedPort);
}
}
@ImportTestcontainers
static class NonStaticDynamicPropertySourceMethod {
@DynamicPropertySource
void containerProperties(DynamicPropertyRegistry registry) {
}
}
@ImportTestcontainers
static class BadArgsDynamicPropertySourceMethod {
@DynamicPropertySource
void containerProperties() {
}
}
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2012-2024 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;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
/**
* Container definitions for {@link LoadTimeWeaverAwareConsumerImportTestcontainersTests}.
*
* @author Andy Wilkinson
*/
interface LoadTimeWeaverAwareConsumerContainers {
@Container
@ServiceConnection
PostgreSQLContainer<?> postgreSQLContainer = new PostgreSQLContainer<>("postgres:16.1");
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2012-2024 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;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import static org.assertj.core.api.Assertions.assertThat;
@SpringBootTest
@DisabledIfDockerUnavailable
@ImportTestcontainers(LoadTimeWeaverAwareConsumerContainers.class)
public class LoadTimeWeaverAwareConsumerImportTestcontainersTests implements LoadTimeWeaverAwareConsumerContainers {
@Autowired
private LoadTimeWeaverAwareConsumer consumer;
@Test
void loadTimeWeaverAwareBeanCanUseJdbcUrlFromContainerBasedConnectionDetails() {
assertThat(this.consumer.jdbcUrl).isNotNull();
}
@Configuration
@ImportAutoConfiguration(DataSourceAutoConfiguration.class)
static class TestConfiguration {
@Bean
LoadTimeWeaverAwareConsumer loadTimeWeaverAwareConsumer(JdbcConnectionDetails connectionDetails) {
return new LoadTimeWeaverAwareConsumer(connectionDetails);
}
}
static class LoadTimeWeaverAwareConsumer implements LoadTimeWeaverAware {
private final String jdbcUrl;
LoadTimeWeaverAwareConsumer(JdbcConnectionDetails connectionDetails) {
this.jdbcUrl = connectionDetails.getJdbcUrl();
}
@Override
public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
}
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2012-2024 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.lifecycle;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.PostgreSQLContainer;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.testcontainers.lifecycle.TestContainersParallelStartupIntegrationTests.ContainerConfig;
import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration test for parallel startup.
*
* @author Phillip Webb
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = ContainerConfig.class)
@TestPropertySource(properties = "spring.testcontainers.beans.startup=parallel")
@DisabledIfDockerUnavailable
@ExtendWith(OutputCaptureExtension.class)
public class TestContainersParallelStartupIntegrationTests {
@Test
void startsInParallel(CapturedOutput out) {
assertThat(out).contains("-lifecycle-0").contains("-lifecycle-1").contains("-lifecycle-2");
}
@Configuration(proxyBeanMethods = false)
static class ContainerConfig {
@Bean
static PostgreSQLContainer<?> container1() {
return TestImage.container(PostgreSQLContainer.class);
}
@Bean
static PostgreSQLContainer<?> container2() {
return TestImage.container(PostgreSQLContainer.class);
}
@Bean
static PostgreSQLContainer<?> container3() {
return TestImage.container(PostgreSQLContainer.class);
}
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2012-2024 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.lifecycle;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.springframework.boot.test.system.CapturedOutput;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
import org.springframework.boot.testcontainers.lifecycle.TestContainersParallelStartupWithImportTestcontainersIntegrationTests.Containers;
import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration test for parallel startup.
*
* @author Phillip Webb
*/
@ExtendWith(SpringExtension.class)
@TestPropertySource(properties = "spring.testcontainers.beans.startup=parallel")
@DisabledIfDockerUnavailable
@ExtendWith(OutputCaptureExtension.class)
@ImportTestcontainers(Containers.class)
public class TestContainersParallelStartupWithImportTestcontainersIntegrationTests {
@Test
void startsInParallel(CapturedOutput out) {
assertThat(out).contains("-lifecycle-0").contains("-lifecycle-1").contains("-lifecycle-2");
}
static class Containers {
@Container
static PostgreSQLContainer<?> container1 = TestImage.container(PostgreSQLContainer.class);
@Container
static PostgreSQLContainer<?> container2 = TestImage.container(PostgreSQLContainer.class);
@Container
static PostgreSQLContainer<?> container3 = TestImage.container(PostgreSQLContainer.class);
}
}

View File

@@ -0,0 +1,103 @@
/*
* Copyright 2012-2024 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.lifecycle;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.context.ImportTestcontainers;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersImportWithPropertiesInjectedIntoLoadTimeWeaverAwareBeanIntegrationTests.Containers;
import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.weaving.LoadTimeWeaverAware;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;
/**
* Tests for {@link ImportTestcontainers} when properties are being injected into a
* {@link LoadTimeWeaverAware} bean.
*
* @author Phillip Webb
*/
@ExtendWith(SpringExtension.class)
@DisabledIfDockerUnavailable
@ImportTestcontainers(Containers.class)
class TestcontainersImportWithPropertiesInjectedIntoLoadTimeWeaverAwareBeanIntegrationTests {
// gh-38913
@Test
void starts() {
}
@TestConfiguration
@EnableConfigurationProperties(MockDataSourceProperties.class)
static class Config {
@Bean
MockEntityManager mockEntityManager(MockDataSourceProperties properties) {
return new MockEntityManager();
}
}
static class MockEntityManager implements LoadTimeWeaverAware {
@Override
public void setLoadTimeWeaver(LoadTimeWeaver loadTimeWeaver) {
}
}
@ConfigurationProperties("spring.datasource")
public static class MockDataSourceProperties {
private String url;
public String getUrl() {
return this.url;
}
public void setUrl(String url) {
this.url = url;
}
}
static class Containers {
@Container
static PostgreSQLContainer<?> container = TestImage.container(PostgreSQLContainer.class);
@DynamicPropertySource
static void setConnectionProperties(DynamicPropertyRegistry registry) {
registry.add("spring.datasource.url", container::getJdbcUrl);
registry.add("spring.datasource.password", container::getPassword);
registry.add("spring.datasource.username", container::getUsername);
}
}
}

View File

@@ -0,0 +1,123 @@
/*
* Copyright 2012-2024 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.lifecycle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.testcontainers.utility.DockerImageName;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleOrderIntegrationTests.AssertingSpringExtension;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleOrderIntegrationTests.ContainerConfig;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleOrderIntegrationTests.TestConfig;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable;
import org.springframework.boot.testsupport.container.RedisContainer;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link TestcontainersLifecycleBeanPostProcessor} to ensure create
* and destroy events happen in the correct order.
*
* @author Phillip Webb
*/
@ExtendWith(AssertingSpringExtension.class)
@ContextConfiguration(classes = { TestConfig.class, ContainerConfig.class })
@DirtiesContext
@DisabledIfDockerUnavailable
class TestcontainersLifecycleOrderIntegrationTests {
static List<String> events = Collections.synchronizedList(new ArrayList<>());
@Test
void eventsAreOrderedCorrectlyAfterStartup() {
assertThat(events).containsExactly("start-container", "create-bean");
}
@Configuration(proxyBeanMethods = false)
static class ContainerConfig {
@Bean
@ServiceConnection("redis")
RedisContainer redisContainer() {
return TestImage.container(EventRecordingRedisContainer.class);
}
}
@Configuration(proxyBeanMethods = false)
static class TestConfig {
@Bean
TestBean testBean() {
events.add("create-bean");
return new TestBean();
}
}
static class TestBean implements AutoCloseable {
@Override
public void close() throws Exception {
events.add("destroy-bean");
}
}
static class AssertingSpringExtension extends SpringExtension {
@Override
public void afterAll(ExtensionContext context) throws Exception {
super.afterAll(context);
assertThat(events).containsExactly("start-container", "create-bean", "destroy-bean", "stop-container");
}
}
static class EventRecordingRedisContainer extends RedisContainer {
EventRecordingRedisContainer(DockerImageName dockerImageName) {
super(dockerImageName);
}
@Override
public void start() {
events.add("start-container");
super.start();
}
@Override
public void stop() {
events.add("stop-container");
super.stop();
}
}
}

View File

@@ -0,0 +1,200 @@
/*
* Copyright 2012-2024 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.lifecycle;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.testcontainers.utility.DockerImageName;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleOrderWithScopeIntegrationTests.AssertingSpringExtension;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleOrderWithScopeIntegrationTests.ContainerConfig;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleOrderWithScopeIntegrationTests.ScopedContextLoader;
import org.springframework.boot.testcontainers.lifecycle.TestcontainersLifecycleOrderWithScopeIntegrationTests.TestConfig;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.DisabledIfDockerUnavailable;
import org.springframework.boot.testsupport.container.RedisContainer;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link TestcontainersLifecycleBeanPostProcessor} to ensure create
* and destroy events happen in the correct order.
*
* @author Phillip Webb
*/
@ExtendWith(AssertingSpringExtension.class)
@ContextConfiguration(loader = ScopedContextLoader.class, classes = { TestConfig.class, ContainerConfig.class })
@DirtiesContext
@DisabledIfDockerUnavailable
class TestcontainersLifecycleOrderWithScopeIntegrationTests {
static List<String> events = Collections.synchronizedList(new ArrayList<>());
@Test
void eventsAreOrderedCorrectlyAfterStartup() {
assertThat(events).containsExactly("start-container", "create-bean");
}
@Configuration(proxyBeanMethods = false)
static class ContainerConfig {
@Bean
@Scope("custom")
@ServiceConnection("redis")
RedisContainer redisContainer() {
return TestImage.container(EventRecordingRedisContainer.class);
}
}
@Configuration(proxyBeanMethods = false)
static class TestConfig {
@Bean
TestBean testBean() {
events.add("create-bean");
return new TestBean();
}
}
static class TestBean implements AutoCloseable {
@Override
public void close() throws Exception {
events.add("destroy-bean");
}
}
static class AssertingSpringExtension extends SpringExtension {
@Override
public void afterAll(ExtensionContext context) throws Exception {
super.afterAll(context);
assertThat(events).containsExactly("start-container", "create-bean", "destroy-bean", "stop-container");
}
}
static class EventRecordingRedisContainer extends RedisContainer {
EventRecordingRedisContainer(DockerImageName dockerImageName) {
super(dockerImageName);
}
@Override
public void start() {
events.add("start-container");
super.start();
}
@Override
public void stop() {
events.add("stop-container");
super.stop();
}
}
static class ScopedContextLoader extends AnnotationConfigContextLoader {
@Override
protected GenericApplicationContext createContext() {
CustomScope customScope = new CustomScope();
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext() {
@Override
protected void onClose() {
customScope.destroy();
super.onClose();
}
};
context.getBeanFactory().registerScope("custom", customScope);
return context;
}
}
static class CustomScope implements org.springframework.beans.factory.config.Scope {
private Map<String, Object> instances = new HashMap<>();
private MultiValueMap<String, Runnable> destructors = new LinkedMultiValueMap<>();
@Override
public Object get(String name, ObjectFactory<?> objectFactory) {
return this.instances.computeIfAbsent(name, (key) -> objectFactory.getObject());
}
@Override
public Object remove(String name) {
synchronized (this) {
Object removed = this.instances.remove(name);
this.destructors.get(name).forEach(Runnable::run);
this.destructors.remove(name);
return removed;
}
}
@Override
public void registerDestructionCallback(String name, Runnable callback) {
this.destructors.add(name, callback);
}
@Override
public Object resolveContextualObject(String key) {
return null;
}
@Override
public String getConversationId() {
return null;
}
void destroy() {
synchronized (this) {
this.destructors.forEach((name, actions) -> actions.forEach(Runnable::run));
this.destructors.clear();
this.instances.clear();
}
}
}
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2012-2024 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.activemq;
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.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.JmsAutoConfiguration;
import org.springframework.boot.autoconfigure.jms.activemq.ActiveMQAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.ActiveMQContainer;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jms.annotation.JmsListener;
import org.springframework.jms.core.JmsMessagingTemplate;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link ActiveMQContainerConnectionDetailsFactory}.
*
* @author Eddú Meléndez
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class ActiveMQContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final ActiveMQContainer activemq = TestImage.container(ActiveMQContainer.class);
@Autowired
private JmsMessagingTemplate jmsTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToActiveMQContainer() {
this.jmsTemplate.convertAndSend("sample.queue", "message");
Awaitility.waitAtMost(Duration.ofMinutes(1))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("message"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration({ ActiveMQAutoConfiguration.class, JmsAutoConfiguration.class })
static class TestConfiguration {
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@JmsListener(destination = "sample.queue")
void processMessage(String message) {
this.messages.add(message);
}
}
}

View File

@@ -0,0 +1,99 @@
/*
* Copyright 2012-2024 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.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.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
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 RabbitContainerConnectionDetailsFactory}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class RabbitContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final RabbitMQContainer rabbit = TestImage.container(RabbitMQContainer.class);
@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,67 @@
/*
* Copyright 2012-2024 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.cassandra;
import com.datastax.oss.driver.api.core.CqlSession;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.CassandraContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
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 CassandraContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class CassandraContainerConnectionDetailsFactoryTests {
@Container
@ServiceConnection
static final CassandraContainer<?> cassandra = TestImage.container(CassandraContainer.class);
@Autowired(required = false)
private CassandraConnectionDetails connectionDetails;
@Autowired
private CqlSession cqlSession;
@Test
void connectionCanBeMadeToCassandraContainer() {
assertThat(this.connectionDetails).isNotNull();
assertThat(this.cqlSession.getMetadata().getNodes()).hasSize(1);
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(CassandraAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2012-2024 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.couchbase;
import com.couchbase.client.java.Cluster;
import org.junit.jupiter.api.Test;
import org.testcontainers.couchbase.BucketDefinition;
import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.couchbase.CouchbaseService;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration;
import org.springframework.boot.autoconfigure.couchbase.CouchbaseConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
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 CouchbaseContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class CouchbaseContainerConnectionDetailsFactoryTests {
@Container
@ServiceConnection
static final CouchbaseContainer couchbase = TestImage.container(CouchbaseContainer.class)
.withEnabledServices(CouchbaseService.KV, CouchbaseService.INDEX, CouchbaseService.QUERY)
.withBucket(new BucketDefinition("cbbucket"));
@Autowired(required = false)
private CouchbaseConnectionDetails connectionDetails;
@Autowired
private Cluster cluster;
@Test
void connectionCanBeMadeToCouchbaseContainer() {
assertThat(this.connectionDetails).isNotNull();
assertThat(this.cluster.diagnostics().endpoints()).hasSize(1);
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(CouchbaseAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,71 @@
/*
* Copyright 2012-2024 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.elasticsearch;
import java.io.IOException;
import co.elastic.clients.elasticsearch.ElasticsearchClient;
import org.junit.jupiter.api.Test;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchClientAutoConfiguration;
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
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 ElasticsearchContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class ElasticsearchContainerConnectionDetailsFactoryTests {
@Container
@ServiceConnection
static final ElasticsearchContainer elasticsearch = TestImage.container(ElasticsearchContainer.class);
@Autowired(required = false)
private ElasticsearchConnectionDetails connectionDetails;
@Autowired
private ElasticsearchClient client;
@Test
void connectionCanBeMadeToElasticsearchContainer() throws IOException {
assertThat(this.connectionDetails).isNotNull();
assertThat(this.client.cluster().health().numberOfNodes()).isEqualTo(1);
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration({ ElasticsearchClientAutoConfiguration.class,
ElasticsearchRestClientAutoConfiguration.class })
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2012-2024 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.flyway;
import org.flywaydb.core.Flyway;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
/**
* Tests for {@link FlywayContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class FlywayContainerConnectionDetailsFactoryTests {
@Container
@ServiceConnection
static final PostgreSQLContainer<?> postgres = TestImage.container(PostgreSQLContainer.class);
@Autowired(required = false)
private JdbcConnectionDetails connectionDetails;
@Autowired
private Flyway flyway;
@Test
void connectionCanBeMadeToJdbcContainer() {
assertThat(this.connectionDetails).isNotNull();
JdbcTemplate jdbc = new JdbcTemplate(this.flyway.getConfiguration().getDataSource());
assertThatNoException().isThrownBy(() -> jdbc.execute("SELECT * from public.flyway_schema_history"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(FlywayAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,72 @@
/*
* Copyright 2012-2024 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.jdbc;
import javax.sql.DataSource;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
/**
* Tests for {@link JdbcContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class JdbcContainerConnectionDetailsFactoryTests {
@Container
@ServiceConnection
static final PostgreSQLContainer<?> postgres = TestImage.container(PostgreSQLContainer.class);
@Autowired(required = false)
private JdbcConnectionDetails connectionDetails;
@Autowired
private DataSource dataSource;
@Test
void connectionCanBeMadeToJdbcContainer() {
assertThat(this.connectionDetails).isNotNull();
JdbcTemplate jdbc = new JdbcTemplate(this.dataSource);
assertThatNoException().isThrownBy(() -> jdbc.execute(DatabaseDriver.POSTGRESQL.getValidationQuery()));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(DataSourceAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2012-2024 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.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
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 KafkaContainerConnectionDetailsFactory}.
*
* @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 KafkaContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final KafkaContainer kafka = TestImage.container(KafkaContainer.class);
@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,70 @@
/*
* Copyright 2012-2024 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.liquibase;
import liquibase.integration.spring.SpringLiquibase;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PostgreSQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatNoException;
/**
* Tests for {@link LiquibaseContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class LiquibaseContainerConnectionDetailsFactoryTests {
@Container
@ServiceConnection
static final PostgreSQLContainer<?> postgres = TestImage.container(PostgreSQLContainer.class);
@Autowired(required = false)
private JdbcConnectionDetails connectionDetails;
@Autowired
private SpringLiquibase liquibase;
@Test
void connectionCanBeMadeToJdbcContainer() {
assertThat(this.connectionDetails).isNotNull();
JdbcTemplate jdbc = new JdbcTemplate(this.liquibase.getDataSource());
assertThatNoException().isThrownBy(() -> jdbc.execute("SELECT * from example"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(LiquibaseAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,118 @@
/*
* Copyright 2012-2024 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.otlp;
import java.time.Duration;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.DistributionSummary;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Timer;
import io.restassured.RestAssured;
import io.restassured.response.Response;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.utility.MountableFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.metrics.export.otlp.OtlpMetricsExportAutoConfiguration;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.matchesPattern;
/**
* Tests for {@link OpenTelemetryMetricsContainerConnectionDetailsFactory}.
*
* @author Eddú Meléndez
* @author Jonatan Ivanov
*/
@SpringJUnitConfig
@TestPropertySource(properties = { "management.otlp.metrics.export.resource-attributes.service.name=test",
"management.otlp.metrics.export.step=1s" })
@Testcontainers(disabledWithoutDocker = true)
class OpenTelemetryMetricsContainerConnectionDetailsFactoryIntegrationTests {
private static final String OPENMETRICS_001 = "application/openmetrics-text; version=0.0.1; charset=utf-8";
private static final String CONFIG_FILE_NAME = "collector-config.yml";
@Container
@ServiceConnection
static final GenericContainer<?> container = TestImage.OPENTELEMETRY.genericContainer()
.withCommand("--config=/etc/" + CONFIG_FILE_NAME)
.withCopyToContainer(MountableFile.forClasspathResource(CONFIG_FILE_NAME), "/etc/" + CONFIG_FILE_NAME)
.withExposedPorts(4318, 9090);
@Autowired
private MeterRegistry meterRegistry;
@Test
void connectionCanBeMadeToOpenTelemetryCollectorContainer() {
Counter.builder("test.counter").register(this.meterRegistry).increment(42);
Gauge.builder("test.gauge", () -> 12).register(this.meterRegistry);
Timer.builder("test.timer").register(this.meterRegistry).record(Duration.ofMillis(123));
DistributionSummary.builder("test.distributionsummary").register(this.meterRegistry).record(24);
Awaitility.await()
.atMost(Duration.ofSeconds(5))
.pollDelay(Duration.ofMillis(100))
.pollInterval(Duration.ofMillis(100))
.untilAsserted(() -> whenPrometheusScraped().then()
.statusCode(200)
.contentType(OPENMETRICS_001)
.body(endsWith("# EOF\n"), containsString("service_name")));
whenPrometheusScraped().then()
.body(containsString(
"{job=\"test\",service_name=\"test\",telemetry_sdk_language=\"java\",telemetry_sdk_name=\"io.micrometer\""),
matchesPattern("(?s)^.*test_counter\\{.+} 42\\.0\\n.*$"),
matchesPattern("(?s)^.*test_gauge\\{.+} 12\\.0\\n.*$"),
matchesPattern("(?s)^.*test_timer_count\\{.+} 1\\n.*$"),
matchesPattern("(?s)^.*test_timer_sum\\{.+} 123\\.0\\n.*$"),
matchesPattern("(?s)^.*test_timer_bucket\\{.+,le=\"\\+Inf\"} 1\\n.*$"),
matchesPattern("(?s)^.*test_distributionsummary_count\\{.+} 1\\n.*$"),
matchesPattern("(?s)^.*test_distributionsummary_sum\\{.+} 24\\.0\\n.*$"),
matchesPattern("(?s)^.*test_distributionsummary_bucket\\{.+,le=\"\\+Inf\"} 1\\n.*$"));
}
private Response whenPrometheusScraped() {
return RestAssured.given().port(container.getMappedPort(9090)).accept(OPENMETRICS_001).when().get("/metrics");
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(OtlpMetricsExportAutoConfiguration.class)
static class TestConfiguration {
@Bean
Clock customClock() {
return Clock.SYSTEM;
}
}
}

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2012-2024 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.otlp;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.otlp.OtlpTracingConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
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 OpenTelemetryTracingContainerConnectionDetailsFactory}.
*
* @author Eddú Meléndez
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class OpenTelemetryTracingContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final GenericContainer<?> container = TestImage.OPENTELEMETRY.genericContainer().withExposedPorts(4318);
@Autowired
private OtlpTracingConnectionDetails connectionDetails;
@Test
void connectionCanBeMadeToOpenTelemetryContainer() {
assertThat(this.connectionDetails.getUrl())
.isEqualTo("http://" + container.getHost() + ":" + container.getMappedPort(4318) + "/v1/traces");
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(OtlpAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2012-2024 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.pulsar;
import java.time.Duration;
import java.util.ArrayList;
import java.util.List;
import org.apache.pulsar.client.api.PulsarClientException;
import org.awaitility.Awaitility;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.PulsarContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.pulsar.PulsarAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.pulsar.annotation.PulsarListener;
import org.springframework.pulsar.core.PulsarTemplate;
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 PulsarContainerConnectionDetailsFactory}.
*
* @author Chris Bono
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
@TestPropertySource(properties = { "spring.pulsar.consumer.subscription.initial-position=earliest" })
class PulsarContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
@SuppressWarnings("unused")
static final PulsarContainer pulsar = TestImage.container(PulsarContainer.class);
@Autowired
private PulsarTemplate<String> pulsarTemplate;
@Autowired
private TestListener listener;
@Test
void connectionCanBeMadeToPulsarContainer() throws PulsarClientException {
this.pulsarTemplate.send("test-topic", "test-data");
Awaitility.waitAtMost(Duration.ofSeconds(30))
.untilAsserted(() -> assertThat(this.listener.messages).containsExactly("test-data"));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(PulsarAutoConfiguration.class)
static class TestConfiguration {
@Bean
TestListener testListener() {
return new TestListener();
}
}
static class TestListener {
private final List<String> messages = new ArrayList<>();
@PulsarListener(topics = "test-topic")
void processMessage(String message) {
this.messages.add(message);
}
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2012-2024 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.r2dbc;
import java.time.Duration;
import io.r2dbc.spi.ConnectionFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.OS;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.oracle.OracleContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.boot.testsupport.junit.DisabledOnOs;
import org.springframework.context.annotation.Configuration;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link OracleFreeR2dbcContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
disabledReason = "The Oracle image has no ARM support")
class OracleFreeR2dbcContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final OracleContainer oracle = TestImage.container(OracleContainer.class);
@Autowired
ConnectionFactory connectionFactory;
@Test
void connectionCanBeMadeToOracleContainer() {
Object result = DatabaseClient.create(this.connectionFactory)
.sql(DatabaseDriver.ORACLE.getValidationQuery())
.map((row, metadata) -> row.get(0))
.first()
.block(Duration.ofSeconds(30));
assertThat(result).isEqualTo("Hello");
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(R2dbcAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2012-2024 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.r2dbc;
import java.time.Duration;
import io.r2dbc.spi.ConnectionFactory;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.OS;
import org.testcontainers.containers.OracleContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.r2dbc.R2dbcAutoConfiguration;
import org.springframework.boot.jdbc.DatabaseDriver;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.boot.testsupport.junit.DisabledOnOs;
import org.springframework.context.annotation.Configuration;
import org.springframework.r2dbc.core.DatabaseClient;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link OracleXeR2dbcContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
@DisabledOnOs(os = { OS.LINUX, OS.MAC }, architecture = "aarch64",
disabledReason = "The Oracle image has no ARM support")
class OracleXeR2dbcContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final OracleContainer oracle = TestImage.container(OracleContainer.class);
@Autowired
ConnectionFactory connectionFactory;
@Test
void connectionCanBeMadeToOracleContainer() {
Object result = DatabaseClient.create(this.connectionFactory)
.sql(DatabaseDriver.ORACLE.getValidationQuery())
.map((row, metadata) -> row.get(0))
.first()
.block(Duration.ofSeconds(30));
assertThat(result).isEqualTo("Hello");
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(R2dbcAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,70 @@
/*
* Copyright 2012-2024 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.redis;
import org.junit.jupiter.api.Test;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
import org.springframework.boot.autoconfigure.data.redis.RedisConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.RedisContainer;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link RedisContainerConnectionDetailsFactory}.
*
* @author Andy Wilkinson
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class RedisContainerConnectionDetailsFactoryTests {
@Container
@ServiceConnection
static final RedisContainer redis = TestImage.container(RedisContainer.class);
@Autowired(required = false)
private RedisConnectionDetails connectionDetails;
@Autowired
private RedisConnectionFactory connectionFactory;
@Test
void connectionCanBeMadeToRedisContainer() {
assertThat(this.connectionDetails).isNotNull();
try (RedisConnection connection = this.connectionFactory.getConnection()) {
assertThat(connection.commands().echo("Hello, World".getBytes())).isEqualTo("Hello, World".getBytes());
}
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(RedisAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,93 @@
/*
* Copyright 2012-2024 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.redpanda;
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.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.testcontainers.redpanda.RedpandaContainer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.kafka.KafkaAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
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 RedpandaContainerConnectionDetailsFactory}.
*
* @author Eddú Meléndez
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
@TestPropertySource(properties = { "spring.kafka.consumer.group-id=test-group",
"spring.kafka.consumer.auto-offset-reset=earliest" })
class RedpandaContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final RedpandaContainer redpanda = TestImage.container(RedpandaContainer.class);
@Autowired
KafkaTemplate<String, String> kafkaTemplate;
@Autowired
TestListener listener;
@Test
void connectionCanBeMadeToRedpandaContainer() {
this.kafkaTemplate.send("test-topic", "test-data");
Awaitility.waitAtMost(Duration.ofSeconds(30))
.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,66 @@
/*
* Copyright 2012-2024 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.zipkin;
import org.junit.jupiter.api.Test;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.tracing.zipkin.ZipkinConnectionDetails;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.container.TestImage;
import org.springframework.boot.testsupport.container.ZipkinContainer;
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 ZipkinContainerConnectionDetailsFactory}.
*
* @author Eddú Meléndez
* @author Moritz Halbritter
*/
@SpringJUnitConfig
@Testcontainers(disabledWithoutDocker = true)
class ZipkinContainerConnectionDetailsFactoryIntegrationTests {
@Container
@ServiceConnection
static final GenericContainer<?> zipkin = TestImage.container(ZipkinContainer.class);
@Autowired(required = false)
private ZipkinConnectionDetails connectionDetails;
@Test
void connectionCanBeMadeToZipkinContainer() {
assertThat(this.connectionDetails).isNotNull();
assertThat(this.connectionDetails.getSpanEndpoint())
.startsWith("http://" + zipkin.getHost() + ":" + zipkin.getMappedPort(9411));
}
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(ZipkinAutoConfiguration.class)
static class TestConfiguration {
}
}

View File

@@ -0,0 +1,20 @@
receivers:
otlp:
protocols:
grpc:
http:
exporters:
# https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/prometheusexporter
prometheus:
endpoint: '0.0.0.0:9090'
metric_expiration: 1m
enable_open_metrics: true
resource_to_telemetry_conversion:
enabled: true
service:
pipelines:
metrics:
receivers: [otlp]
exporters: [prometheus]

View File

@@ -0,0 +1,20 @@
databaseChangeLog:
- changeSet:
id: 1
author: wilkinsona
changes:
- createTable:
tableName: example
columns:
- column:
name: id
type: int
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: name
type: varchar(50)
constraints:
nullable: false

View File

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

View File

@@ -0,0 +1 @@
spring.test.context.cache.maxSize=1