Skip to content

Commit

Permalink
Support ServiceConnection beans in slice tests
Browse files Browse the repository at this point in the history
Currently, in order to use `@ServiceConnection` in beans along with
slice test annotations `@ImportAutoConfiguration(ServiceConnectionAutoConfiguration.class)`
should be added to make it work. This commit register
`ServiceConnectionAutoConfiguration` in specific slice test annotations.

See spring-projectsgh-35252
  • Loading branch information
eddumelendez committed Jun 23, 2023
1 parent e33cec5 commit 96444ee
Show file tree
Hide file tree
Showing 20 changed files with 546 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ dependencies {
optional("org.springframework:spring-web")
optional("org.springframework:spring-webmvc")
optional("org.springframework:spring-webflux")
optional(project(":spring-boot-project:spring-boot-testcontainers"))
optional("org.springframework.data:spring-data-cassandra") {
exclude group: "org.slf4j", module: "jcl-over-slf4j"
}
Expand Down Expand Up @@ -63,7 +64,6 @@ dependencies {
testImplementation(project(":spring-boot-project:spring-boot-actuator"))
testImplementation(project(":spring-boot-project:spring-boot-actuator-autoconfigure"))
testImplementation(project(":spring-boot-project:spring-boot-tools:spring-boot-test-support"))
testImplementation(project(":spring-boot-project:spring-boot-testcontainers"))
testImplementation("ch.qos.logback:logback-classic")
testImplementation("com.fasterxml.jackson.module:jackson-module-parameter-names")
testImplementation("com.h2database:h2")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* 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.test.autoconfigure.service.connection;

import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureOrder;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.testcontainers.service.connection.ServiceConnectionAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;

/**
* Auto-configuration for ServiceConnection.
*
* @author Eddú Meléndez
* @since 3.1.2
*/
@AutoConfiguration
@AutoConfigureOrder(Ordered.HIGHEST_PRECEDENCE)
@ConditionalOnClass(ServiceConnectionAutoConfiguration.class)
public class TestcontainersServiceConnectionAutoConfiguration {

@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(ServiceConnectionAutoConfiguration.class)
static class ImportAutoConfigurationTest {

}

}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataCassandra auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraDataAutoConfiguration
org.springframework.boot.autoconfigure.data.cassandra.CassandraReactiveDataAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# AutoConfigureDataCouchbase auto-configuration imports

org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.couchbase.CouchbaseAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseDataAutoConfiguration
org.springframework.boot.autoconfigure.data.couchbase.CouchbaseReactiveDataAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataElasticsearch auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.elasticsearch.ElasticsearchDataAutoConfiguration
org.springframework.boot.autoconfigure.data.elasticsearch.ReactiveElasticsearchRepositoriesAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataJdbc auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.data.jdbc.JdbcRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataMongo auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration
org.springframework.boot.autoconfigure.data.mongo.MongoReactiveRepositoriesAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataNeo4j auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration
org.springframework.boot.autoconfigure.data.neo4j.Neo4jDataAutoConfiguration
org.springframework.boot.autoconfigure.data.neo4j.Neo4jReactiveDataAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataR2dbc auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.data.r2dbc.R2dbcDataAutoConfiguration
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataRedis auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration
org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureJdbc auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# AutoConfigureTestDatabase auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureJooq auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# AutoConfigureDataJpa auto-configuration imports
org.springframework.boot.test.autoconfigure.service.connection.TestcontainersServiceConnectionAutoConfiguration
org.springframework.boot.autoconfigure.data.jpa.JpaRepositoriesAutoConfiguration
org.springframework.boot.autoconfigure.flyway.FlywayAutoConfiguration
org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/*
* 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.test.autoconfigure.data.cassandra;

import java.util.UUID;

import com.datastax.oss.driver.api.core.CqlSession;
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
import org.junit.jupiter.api.Test;
import org.testcontainers.junit.jupiter.Testcontainers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.testcontainers.CassandraContainer;
import org.springframework.context.annotation.Bean;
import org.springframework.data.cassandra.core.CassandraTemplate;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Integration test for {@link DataCassandraTest @DataCassandraTest}.
*
* @author Artsiom Yudovin
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Eddú Meléndez
*/
@DataCassandraTest(properties = { "spring.cassandra.schema-action=create-if-not-exists",
"spring.cassandra.connection.connect-timeout=60s", "spring.cassandra.connection.init-query-timeout=60s",
"spring.cassandra.request.timeout=60s" })
@Testcontainers(disabledWithoutDocker = true)
class DataCassandraTestWithServiceConnectionBeanIntegrationTests {

@Autowired
private CassandraTemplate cassandraTemplate;

@Autowired
private ExampleRepository exampleRepository;

@Test
void testRepository() {
ExampleEntity entity = new ExampleEntity();
entity.setDescription("Look, new @DataCassandraTest!");
String id = UUID.randomUUID().toString();
entity.setId(id);
ExampleEntity savedEntity = this.exampleRepository.save(entity);
ExampleEntity getEntity = this.cassandraTemplate.selectOneById(id, ExampleEntity.class);
assertThat(getEntity).isNotNull();
assertThat(getEntity.getId()).isNotNull();
assertThat(getEntity.getId()).isEqualTo(savedEntity.getId());
this.exampleRepository.deleteAll();
}

@TestConfiguration(proxyBeanMethods = false)
static class KeyspaceTestConfiguration {

@Bean
@ServiceConnection
CassandraContainer cassandra() {
return new CassandraContainer();
}

@Bean
CqlSession cqlSession(CqlSessionBuilder cqlSessionBuilder) {
try (CqlSession session = cqlSessionBuilder.build()) {
session.execute("CREATE KEYSPACE IF NOT EXISTS boot_test"
+ " WITH REPLICATION = { 'class' : 'SimpleStrategy', 'replication_factor' : 1 };");
}
return cqlSessionBuilder.withKeyspace("boot_test").build();
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.test.autoconfigure.data.couchbase;

import java.time.Duration;

import org.junit.jupiter.api.Test;
import org.testcontainers.couchbase.BucketDefinition;
import org.testcontainers.couchbase.CouchbaseContainer;
import org.testcontainers.junit.jupiter.Testcontainers;

import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.data.couchbase.core.CouchbaseTemplate;
import org.springframework.test.annotation.DirtiesContext;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;

/**
* Integration test for {@link DataCouchbaseTest @DataCouchbaseTest}.
*
* @author Eddú Meléndez
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@DataCouchbaseTest(
properties = { "spring.couchbase.env.timeouts.connect=2m", "spring.data.couchbase.bucket-name=cbbucket" })
@Testcontainers(disabledWithoutDocker = true)
class DataCouchbaseTestWithServiceConnectionBeanIntegrationTests {

private static final String BUCKET_NAME = "cbbucket";

@Autowired
private CouchbaseTemplate couchbaseTemplate;

@Autowired
private ExampleRepository exampleRepository;

@Test
void testRepository() {
ExampleDocument document = new ExampleDocument();
document.setText("Look, new @DataCouchbaseTest!");
document = this.exampleRepository.save(document);
assertThat(document.getId()).isNotNull();
assertThat(this.couchbaseTemplate.getBucketName()).isEqualTo(BUCKET_NAME);
this.exampleRepository.deleteAll();
}

@TestConfiguration(proxyBeanMethods = false)
static class ContainerConfig {

@Bean
@ServiceConnection
CouchbaseContainer couchbase() {
return new CouchbaseContainer(DockerImageNames.couchbase()).withStartupAttempts(5)
.withStartupTimeout(Duration.ofMinutes(10))
.withBucket(new BucketDefinition(BUCKET_NAME));
}

}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* 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.test.autoconfigure.data.elasticsearch;

import java.time.Duration;
import java.util.UUID;

import org.junit.jupiter.api.Test;
import org.testcontainers.elasticsearch.ElasticsearchContainer;
import org.testcontainers.junit.jupiter.Testcontainers;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
import org.springframework.boot.testsupport.testcontainers.DockerImageNames;
import org.springframework.context.annotation.Bean;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Sample test for {@link DataElasticsearchTest @DataElasticsearchTest}
*
* @author Eddú Meléndez
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
*/
@DataElasticsearchTest
@Testcontainers(disabledWithoutDocker = true)
class DataElasticsearchTestWithServiceConnectionBeanIntegrationTests {

;

@Autowired
private ElasticsearchTemplate elasticsearchTemplate;

@Autowired
private ExampleRepository exampleRepository;

@Test
void testRepository() {
ExampleDocument document = new ExampleDocument();
document.setText("Look, new @DataElasticsearchTest!");
String id = UUID.randomUUID().toString();
document.setId(id);
ExampleDocument savedDocument = this.exampleRepository.save(document);
ExampleDocument getDocument = this.elasticsearchTemplate.get(id, ExampleDocument.class);
assertThat(getDocument).isNotNull();
assertThat(getDocument.getId()).isNotNull();
assertThat(getDocument.getId()).isEqualTo(savedDocument.getId());
this.exampleRepository.deleteAll();
}

@TestConfiguration(proxyBeanMethods = false)
static class ContainerConfig {

@Bean
@ServiceConnection
ElasticsearchContainer elasticsearch() {
return new ElasticsearchContainer(DockerImageNames.elasticsearch())
.withEnv("ES_JAVA_OPTS", "-Xms32m -Xmx512m")
.withStartupAttempts(5)
.withStartupTimeout(Duration.ofMinutes(10));
}

}

}

0 comments on commit 96444ee

Please sign in to comment.