Refactor testcontainers service connections
Update restcontainers service connections support so that technology specific `@ServiceConnector` annotations are not longer required. A single `@ServiceConnector` annotation can now be used to create all `ConnectionDetail` beans. Closes gh-35017pull/35031/head
parent
11dac5b5b7
commit
81a972af8d
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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 java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories;
|
||||
import org.springframework.core.log.LogMessage;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Class used to register bean definitions from a list of
|
||||
* {@link ContainerConnectionSource} instances.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ContainerConnectionSourcesRegistrar {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ContainerConnectionSourcesRegistrar.class);
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
private final ConnectionDetailsFactories connectionDetailsFactories;
|
||||
|
||||
private final List<ContainerConnectionSource<?, ?>> sources;
|
||||
|
||||
ContainerConnectionSourcesRegistrar(ListableBeanFactory beanFactory,
|
||||
ConnectionDetailsFactories connectionDetailsFactories, List<ContainerConnectionSource<?, ?>> sources) {
|
||||
this.beanFactory = beanFactory;
|
||||
this.connectionDetailsFactories = connectionDetailsFactories;
|
||||
this.sources = sources;
|
||||
}
|
||||
|
||||
void registerBeanDefinitions(BeanDefinitionRegistry registry) {
|
||||
this.sources.forEach((source) -> registerBeanDefinition(registry, source));
|
||||
}
|
||||
|
||||
private void registerBeanDefinition(BeanDefinitionRegistry registry, ContainerConnectionSource<?, ?> source) {
|
||||
getConnectionDetails(source)
|
||||
.forEach((connectionDetailsType, connectionDetails) -> registerBeanDefinition(registry, source,
|
||||
connectionDetailsType, connectionDetails));
|
||||
}
|
||||
|
||||
private <S> Map<Class<?>, ConnectionDetails> getConnectionDetails(S source) {
|
||||
Map<Class<?>, ConnectionDetails> connectionDetails = this.connectionDetailsFactories
|
||||
.getConnectionDetails(source);
|
||||
Assert.state(!connectionDetails.isEmpty(), () -> "No connection details created for %s".formatted(source));
|
||||
return connectionDetails;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> void registerBeanDefinition(BeanDefinitionRegistry registry, ContainerConnectionSource<?, ?> source,
|
||||
Class<?> connectionDetailsType, ConnectionDetails connectionDetails) {
|
||||
String[] existingBeans = this.beanFactory.getBeanNamesForType(connectionDetailsType);
|
||||
if (!ObjectUtils.isEmpty(existingBeans)) {
|
||||
logger.debug(LogMessage.of(() -> "Skipping registration of %s due to existing beans %s".formatted(source,
|
||||
Arrays.asList(existingBeans))));
|
||||
return;
|
||||
}
|
||||
String beanName = getBeanName(source, connectionDetails);
|
||||
Class<T> beanType = (Class<T>) connectionDetails.getClass();
|
||||
Supplier<T> beanSupplier = () -> (T) connectionDetails;
|
||||
logger.debug(LogMessage.of(() -> "Registering '%s' for %s".formatted(beanName, source)));
|
||||
registry.registerBeanDefinition(beanName, new RootBeanDefinition(beanType, beanSupplier));
|
||||
}
|
||||
|
||||
private String getBeanName(ContainerConnectionSource<?, ?> source, ConnectionDetails connectionDetails) {
|
||||
List<String> parts = new ArrayList<>();
|
||||
parts.add(ClassUtils.getShortNameAsProperty(connectionDetails.getClass()));
|
||||
parts.add("for");
|
||||
parts.add(source.getBeanNameSuffix());
|
||||
return StringUtils.uncapitalize(parts.stream().map(StringUtils::capitalize).collect(Collectors.joining()));
|
||||
}
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.amqp.RabbitConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a RabbitMQ service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
* @see RabbitConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(RabbitConnectionDetails.class)
|
||||
public @interface RabbitServiceConnection {
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.cassandra;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.cassandra.CassandraConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a Cassandra service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
* @see CassandraConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(CassandraConnectionDetails.class)
|
||||
public @interface CassandraServiceConnection {
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.couchbase;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.couchbase.CouchbaseConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a Couchbase service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
* @see CouchbaseConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(CouchbaseConnectionDetails.class)
|
||||
public @interface CouchbaseServiceConnection {
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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.elasticsearch;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a Elasticsearch service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
* @see ElasticsearchConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(ElasticsearchConnectionDetails.class)
|
||||
public @interface ElasticsearchServiceConnection {
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* 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 java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.influx.InfluxDbConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides an InfluxDB service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
* @since 3.1.0
|
||||
* @see InfluxDbConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(InfluxDbConnectionDetails.class)
|
||||
public @interface InfluxDbServiceConnection {
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.jdbc;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a JDBC database service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
* @see JdbcConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(JdbcConnectionDetails.class)
|
||||
public @interface JdbcServiceConnection {
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.kafka.KafkaConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a Kafka service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
* @see KafkaConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(KafkaConnectionDetails.class)
|
||||
public @interface KafkaServiceConnection {
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.mongo;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a Mongo service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
* @see MongoConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(MongoConnectionDetails.class)
|
||||
public @interface MongoServiceConnection {
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.neo4j;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates a field provides a Neo4j service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
* @see Neo4jConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(Neo4jConnectionDetails.class)
|
||||
public @interface Neo4jServiceConnection {
|
||||
|
||||
}
|
17
spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/r2dbc/SqlServerR2dbcContainerConnectionDetailsFactory.java → spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MsSqlServerR2dbcContainerConnectionDetailsFactory.java
17
spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/r2dbc/SqlServerR2dbcContainerConnectionDetailsFactory.java → spring-boot-project/spring-boot-testcontainers/src/main/java/org/springframework/boot/testcontainers/service/connection/r2dbc/MsSqlServerR2dbcContainerConnectionDetailsFactory.java
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.r2dbc;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.r2dbc.R2dbcConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates a field provides a R2DBC database service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
* @see ServiceConnection
|
||||
* @see R2dbcConnectionDetails
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(R2dbcConnectionDetails.class)
|
||||
public @interface R2dbcServiceConnection {
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.redis;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisConnectionDetails;
|
||||
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
|
||||
|
||||
/**
|
||||
* Annotation that indicates that a field provides a Redis service connection.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @since 3.1.0
|
||||
* @see RedisConnectionDetails
|
||||
* @see ServiceConnection
|
||||
*/
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.FIELD, ElementType.TYPE })
|
||||
@ServiceConnection(RedisConnectionDetails.class)
|
||||
public @interface RedisServiceConnection {
|
||||
|
||||
}
|
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* 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 java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactory;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link ContainerConnectionDetailsFactory}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ContainerConnectionDetailsFactoryTests {
|
||||
|
||||
private String beanNameSuffix;
|
||||
|
||||
private Origin origin;
|
||||
|
||||
private JdbcDatabaseContainer<?> container;
|
||||
|
||||
private MergedAnnotation<ServiceConnection> annotation;
|
||||
|
||||
private ContainerConnectionSource<?, ?> source;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.beanNameSuffix = "MyBean";
|
||||
this.origin = mock(Origin.class);
|
||||
this.container = mock(PostgreSQLContainer.class);
|
||||
this.annotation = MergedAnnotation.of(ServiceConnection.class,
|
||||
Map.of("name", "myname", "type", new Class<?>[0]));
|
||||
this.source = new ContainerConnectionSource<>(this.beanNameSuffix, this.origin, this.container,
|
||||
this.annotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getConnectionDetailsWhenTypesMatchAndNoNameRestrictionReturnsDetails() {
|
||||
TestContainerConnectionDetailsFactory factory = new TestContainerConnectionDetailsFactory();
|
||||
ConnectionDetails connectionDetails = getConnectionDetails(factory, this.source);
|
||||
assertThat(connectionDetails).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getConnectionDetailsWhenTypesMatchAndNameRestrictionMatchesReturnsDetails() {
|
||||
TestContainerConnectionDetailsFactory factory = new TestContainerConnectionDetailsFactory("myname");
|
||||
ConnectionDetails connectionDetails = getConnectionDetails(factory, this.source);
|
||||
assertThat(connectionDetails).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getConnectionDetailsWhenTypesMatchAndNameRestrictionDoesNotMatchReturnsNull() {
|
||||
TestContainerConnectionDetailsFactory factory = new TestContainerConnectionDetailsFactory("notmyname");
|
||||
ConnectionDetails connectionDetails = getConnectionDetails(factory, this.source);
|
||||
assertThat(connectionDetails).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getConnectionDetailsWhenContainerTypeDoesNotMatchReturnsNull() {
|
||||
ElasticsearchContainer container = mock(ElasticsearchContainer.class);
|
||||
ContainerConnectionSource<?, ?> source = new ContainerConnectionSource<>(this.beanNameSuffix, this.origin,
|
||||
container, this.annotation);
|
||||
TestContainerConnectionDetailsFactory factory = new TestContainerConnectionDetailsFactory();
|
||||
ConnectionDetails connectionDetails = getConnectionDetails(factory, source);
|
||||
assertThat(connectionDetails).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getConnectionDetailsHasOrigin() {
|
||||
TestContainerConnectionDetailsFactory factory = new TestContainerConnectionDetailsFactory();
|
||||
ConnectionDetails connectionDetails = getConnectionDetails(factory, this.source);
|
||||
assertThat(Origin.from(connectionDetails)).isSameAs(this.origin);
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
private ConnectionDetails getConnectionDetails(ConnectionDetailsFactory<?, ?> factory,
|
||||
ContainerConnectionSource<?, ?> source) {
|
||||
return ((ConnectionDetailsFactory) factory).getConnectionDetails(source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link ContainerConnectionDetailsFactory}.
|
||||
*/
|
||||
static class TestContainerConnectionDetailsFactory
|
||||
extends ContainerConnectionDetailsFactory<JdbcConnectionDetails, JdbcDatabaseContainer<?>> {
|
||||
|
||||
TestContainerConnectionDetailsFactory() {
|
||||
this(ANY_CONNECTION_NAME);
|
||||
}
|
||||
|
||||
TestContainerConnectionDetailsFactory(String connectionName) {
|
||||
super(connectionName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JdbcConnectionDetails getContainerConnectionDetails(
|
||||
ContainerConnectionSource<JdbcConnectionDetails, JdbcDatabaseContainer<?>> source) {
|
||||
return new TestContainerConnectionDetails(source);
|
||||
}
|
||||
|
||||
static class TestContainerConnectionDetails extends ContainerConnectionDetails
|
||||
implements JdbcConnectionDetails {
|
||||
|
||||
TestContainerConnectionDetails(ContainerConnectionSource<?, ?> source) {
|
||||
super(source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return "user";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return "secret";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJdbcUrl() {
|
||||
return "jdbc:example";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,183 @@
|
||||
/*
|
||||
* 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 java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
/**
|
||||
* Tests for {@link ContainerConnectionSource}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ContainerConnectionSourceTests {
|
||||
|
||||
private String beanNameSuffix;
|
||||
|
||||
private Origin origin;
|
||||
|
||||
private JdbcDatabaseContainer<?> container;
|
||||
|
||||
private MergedAnnotation<ServiceConnection> annotation;
|
||||
|
||||
private ContainerConnectionSource<?, ?> source;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.beanNameSuffix = "MyBean";
|
||||
this.origin = mock(Origin.class);
|
||||
this.container = mock(PostgreSQLContainer.class);
|
||||
given(this.container.getDockerImageName()).willReturn("postgres");
|
||||
this.annotation = MergedAnnotation.of(ServiceConnection.class, Map.of("name", "", "type", new Class<?>[0]));
|
||||
this.source = new ContainerConnectionSource<>(this.beanNameSuffix, this.origin, this.container,
|
||||
this.annotation);
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenContainerIsNotInstanceOfContainerTypeReturnsFalse() {
|
||||
String connectionName = null;
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = ElasticsearchContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenContainerIsInstanceOfContainerTypeReturnsTrue() {
|
||||
String connectionName = null;
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionNameDoesNotMatchNameTakenFromAnnotationReturnsFalse() {
|
||||
setupSourceAnnotatedWithName("myname");
|
||||
String connectionName = "othername";
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionNameDoesNotMatchNameTakenFromContainerReturnsFalse() {
|
||||
String connectionName = "othername";
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionNameIsUnrestrictedReturnsTrue() {
|
||||
String connectionName = null;
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionNameMatchesNameTakenFromAnnotationReturnsTrue() {
|
||||
setupSourceAnnotatedWithName("myname");
|
||||
String connectionName = "myname";
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionNameMatchesNameTakenFromContainerReturnsTrue() {
|
||||
String connectionName = "postgres";
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionDetailsTypeNotInAnnotationRestrictionReturnsFalse() {
|
||||
setupSourceAnnotatedWithType(ElasticsearchConnectionDetails.class);
|
||||
String connectionName = null;
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionDetailsTypeInAnnotationRestrictionReturnsTrue() {
|
||||
setupSourceAnnotatedWithType(JdbcConnectionDetails.class);
|
||||
String connectionName = null;
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void acceptsWhenConnectionDetailsTypeIsNotRestrictedReturnsTrue() {
|
||||
String connectionName = null;
|
||||
Class<?> connectionDetailsType = JdbcConnectionDetails.class;
|
||||
Class<?> containerType = JdbcDatabaseContainer.class;
|
||||
assertThat(this.source.accepts(connectionName, connectionDetailsType, containerType)).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void getBeanNameSuffixReturnsBeanNameSuffix() {
|
||||
assertThat(this.source.getBeanNameSuffix()).isEqualTo(this.beanNameSuffix);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getOriginReturnsOrigin() {
|
||||
assertThat(this.source.getOrigin()).isEqualTo(this.origin);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getContainerReturnsContainer() {
|
||||
assertThat(this.source.getContainer()).isSameAs(this.container);
|
||||
}
|
||||
|
||||
@Test
|
||||
void toStringReturnsSensibleString() {
|
||||
assertThat(this.source.toString()).startsWith("@ServiceConnection source for Mock for Origin");
|
||||
}
|
||||
|
||||
private void setupSourceAnnotatedWithName(String name) {
|
||||
this.annotation = MergedAnnotation.of(ServiceConnection.class, Map.of("name", name, "type", new Class<?>[0]));
|
||||
this.source = new ContainerConnectionSource<>(this.beanNameSuffix, this.origin, this.container,
|
||||
this.annotation);
|
||||
}
|
||||
|
||||
private void setupSourceAnnotatedWithType(Class<?> type) {
|
||||
this.annotation = MergedAnnotation.of(ServiceConnection.class,
|
||||
Map.of("name", "", "type", new Class<?>[] { type }));
|
||||
this.source = new ContainerConnectionSource<>(this.beanNameSuffix, this.origin, this.container,
|
||||
this.annotation);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.Test;
|
||||
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Tests for {@link FieldOrigin}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class FieldOriginTests {
|
||||
|
||||
@Test
|
||||
void createWhenFieldIsNullThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new FieldOrigin(null))
|
||||
.withMessage("Field must not be null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void equalsAndHashCode() {
|
||||
Origin o1 = new FieldOrigin(ReflectionUtils.findField(Fields.class, "one"));
|
||||
Origin o2 = new FieldOrigin(ReflectionUtils.findField(Fields.class, "one"));
|
||||
Origin o3 = new FieldOrigin(ReflectionUtils.findField(Fields.class, "two"));
|
||||
assertThat(o1).isEqualTo(o1).isEqualTo(o2).isNotEqualTo(o3);
|
||||
assertThat(o1.hashCode()).isEqualTo(o2.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void toStringReturnsSensibleString() {
|
||||
Origin origin = new FieldOrigin(ReflectionUtils.findField(Fields.class, "one"));
|
||||
assertThat(origin).hasToString("FieldOriginTests.Fields.one");
|
||||
}
|
||||
|
||||
static class Fields {
|
||||
|
||||
String one;
|
||||
|
||||
String two;
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* 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 java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
import org.testcontainers.containers.PostgreSQLContainer;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.beans.factory.support.RootBeanDefinition;
|
||||
import org.springframework.boot.autoconfigure.jdbc.JdbcConnectionDetails;
|
||||
import org.springframework.boot.autoconfigure.service.connection.ConnectionDetailsFactories;
|
||||
import org.springframework.boot.origin.Origin;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.MergedAnnotation;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.BDDMockito.given;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
/**
|
||||
* Tests for {@link ServiceConnectionContextCustomizer}.
|
||||
*
|
||||
* @author Moritz Halbritter
|
||||
* @author Andy Wilkinson
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
class ServiceConnectionContextCustomizerTests {
|
||||
|
||||
private String beanNameSuffix;
|
||||
|
||||
private Origin origin;
|
||||
|
||||
private JdbcDatabaseContainer<?> container;
|
||||
|
||||
private MergedAnnotation<ServiceConnection> annotation;
|
||||
|
||||
private ContainerConnectionSource<?, ?> source;
|
||||
|
||||
private ConnectionDetailsFactories factories;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
this.beanNameSuffix = "MyBean";
|
||||
this.origin = mock(Origin.class);
|
||||
this.container = mock(PostgreSQLContainer.class);
|
||||
this.annotation = MergedAnnotation.of(ServiceConnection.class,
|
||||
Map.of("name", "myname", "type", new Class<?>[0]));
|
||||
this.source = new ContainerConnectionSource<>(this.beanNameSuffix, this.origin, this.container,
|
||||
this.annotation);
|
||||
this.factories = mock(ConnectionDetailsFactories.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizeContextRegistersServiceConnections() {
|
||||
ServiceConnectionContextCustomizer customizer = new ServiceConnectionContextCustomizer(List.of(this.source),
|
||||
this.factories);
|
||||
ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class);
|
||||
DefaultListableBeanFactory beanFactory = spy(new DefaultListableBeanFactory());
|
||||
given(context.getBeanFactory()).willReturn(beanFactory);
|
||||
MergedContextConfiguration mergedConfig = mock(MergedContextConfiguration.class);
|
||||
JdbcConnectionDetails connectionDetails = new TestJdbcConnectionDetails();
|
||||
given(this.factories.getConnectionDetails(this.source))
|
||||
.willReturn(Map.of(JdbcConnectionDetails.class, connectionDetails));
|
||||
customizer.customizeContext(context, mergedConfig);
|
||||
ArgumentCaptor<BeanDefinition> beanDefinitionCaptor = ArgumentCaptor.forClass(BeanDefinition.class);
|
||||
then(beanFactory).should()
|
||||
.registerBeanDefinition(eq("testJdbcConnectionDetailsForMyBean"), beanDefinitionCaptor.capture());
|
||||
RootBeanDefinition beanDefinition = (RootBeanDefinition) beanDefinitionCaptor.getValue();
|
||||
assertThat(beanDefinition.getInstanceSupplier().get()).isSameAs(connectionDetails);
|
||||
assertThat(beanDefinition.getBeanClass()).isEqualTo(TestJdbcConnectionDetails.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
void customizeContextWhenFactoriesHasNoConnectionDetailsThrowsException() {
|
||||
ServiceConnectionContextCustomizer customizer = new ServiceConnectionContextCustomizer(List.of(this.source),
|
||||
this.factories);
|
||||
ConfigurableApplicationContext context = mock(ConfigurableApplicationContext.class);
|
||||
DefaultListableBeanFactory beanFactory = spy(new DefaultListableBeanFactory());
|
||||
given(context.getBeanFactory()).willReturn(beanFactory);
|
||||
MergedContextConfiguration mergedConfig = mock(MergedContextConfiguration.class);
|
||||
assertThatIllegalStateException().isThrownBy(() -> customizer.customizeContext(context, mergedConfig))
|
||||
.withMessageStartingWith("No connection details created for @ServiceConnection source");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test {@link JdbcConnectionDetails}.
|
||||
*/
|
||||
static class TestJdbcConnectionDetails implements JdbcConnectionDetails {
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPassword() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getJdbcUrl() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
12
spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/amqp/RabbitServiceConnectionTests.java → spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/amqp/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
12
spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/amqp/RabbitServiceConnectionTests.java → spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/amqp/RabbitContainerConnectionDetailsFactoryIntegrationTests.java
16
spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/influx/InfluxDbServiceConnectionTests.java → spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/influx/InfluxDbContainerConnectionDetailsFactoryIntegrationTests.java
16
spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/influx/InfluxDbServiceConnectionTests.java → spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/influx/InfluxDbContainerConnectionDetailsFactoryIntegrationTests.java
11
spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/kafka/KafkaServiceConnectionTests.java → spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/kafka/KafkaContainerConnectionDetailsFactoryIntegrationTests.java
11
spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/kafka/KafkaServiceConnectionTests.java → spring-boot-project/spring-boot-testcontainers/src/test/java/org/springframework/boot/testcontainers/service/connection/kafka/KafkaContainerConnectionDetailsFactoryIntegrationTests.java
Loading…
Reference in New Issue