Browse Source
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
78 changed files with 1299 additions and 905 deletions
@ -0,0 +1,106 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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