Update spring-boot-autoconfigure to use docker-test plugin
See gh-41228
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.cassandra;
|
||||
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
import com.datastax.oss.driver.api.core.config.DriverConfigLoader;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.CassandraContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link CassandraAutoConfiguration}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class CassandraAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final CassandraContainer<?> cassandra = TestImage.container(CassandraContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(CassandraAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"spring.cassandra.contact-points:" + cassandra.getHost() + ":" + cassandra.getFirstMappedPort(),
|
||||
"spring.cassandra.local-datacenter=datacenter1", "spring.cassandra.connection.connect-timeout=60s",
|
||||
"spring.cassandra.connection.init-query-timeout=60s", "spring.cassandra.request.timeout=60s");
|
||||
|
||||
@Test
|
||||
void whenTheContextIsClosedThenTheDriverConfigLoaderIsClosed() {
|
||||
this.contextRunner.withUserConfiguration(DriverConfigLoaderSpyConfiguration.class).run((context) -> {
|
||||
assertThat(((BeanDefinitionRegistry) context.getSourceApplicationContext())
|
||||
.getBeanDefinition("cassandraDriverConfigLoader")
|
||||
.getDestroyMethodName()).isEmpty();
|
||||
// Initialize lazy bean
|
||||
context.getBean(CqlSession.class);
|
||||
DriverConfigLoader driverConfigLoader = context.getBean(DriverConfigLoader.class);
|
||||
context.close();
|
||||
then(driverConfigLoader).should().close();
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class DriverConfigLoaderSpyConfiguration {
|
||||
|
||||
@Bean
|
||||
static BeanPostProcessor driverConfigLoaderSpy() {
|
||||
return new BeanPostProcessor() {
|
||||
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
if (bean instanceof DriverConfigLoader) {
|
||||
return spy(bean);
|
||||
}
|
||||
return bean;
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.cassandra;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.datastax.oss.driver.api.core.ConsistencyLevel;
|
||||
import com.datastax.oss.driver.api.core.CqlSession;
|
||||
import com.datastax.oss.driver.api.core.CqlSessionBuilder;
|
||||
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.rnorth.ducttape.TimeoutException;
|
||||
import org.rnorth.ducttape.unreliables.Unreliables;
|
||||
import org.testcontainers.containers.CassandraContainer;
|
||||
import org.testcontainers.containers.ContainerLaunchException;
|
||||
import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy;
|
||||
import org.testcontainers.images.builder.Transferable;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import org.testcontainers.utility.DockerImageName;
|
||||
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.util.StreamUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
/**
|
||||
* Tests for {@link CassandraAutoConfiguration} that only uses password authentication.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class CassandraAutoConfigurationWithPasswordAuthenticationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final PasswordAuthenticatorCassandraContainer cassandra = TestImage
|
||||
.container(PasswordAuthenticatorCassandraContainer.class)
|
||||
.withStartupAttempts(5)
|
||||
.waitingFor(new CassandraWaitStrategy());
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(CassandraAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"spring.cassandra.contact-points:" + cassandra.getHost() + ":" + cassandra.getFirstMappedPort(),
|
||||
"spring.cassandra.local-datacenter=datacenter1", "spring.cassandra.connection.connect-timeout=60s",
|
||||
"spring.cassandra.connection.init-query-timeout=60s", "spring.cassandra.request.timeout=60s");
|
||||
|
||||
@Test
|
||||
void authenticationWithValidUsernameAndPassword() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.cassandra.username=cassandra", "spring.cassandra.password=cassandra")
|
||||
.run((context) -> {
|
||||
SimpleStatement select = SimpleStatement.newInstance("SELECT release_version FROM system.local")
|
||||
.setConsistencyLevel(ConsistencyLevel.LOCAL_ONE);
|
||||
assertThat(context.getBean(CqlSession.class).execute(select).one()).isNotNull();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void authenticationWithInvalidCredentials() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.cassandra.username=not-a-user", "spring.cassandra.password=invalid-password")
|
||||
.run((context) -> assertThatExceptionOfType(BeanCreationException.class)
|
||||
.isThrownBy(() -> context.getBean(CqlSession.class))
|
||||
.withMessageContaining("Authentication error"));
|
||||
}
|
||||
|
||||
static final class PasswordAuthenticatorCassandraContainer
|
||||
extends CassandraContainer<PasswordAuthenticatorCassandraContainer> {
|
||||
|
||||
PasswordAuthenticatorCassandraContainer(DockerImageName dockerImageName) {
|
||||
super(dockerImageName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void containerIsCreated(String containerId) {
|
||||
String config = copyFileFromContainer("/etc/cassandra/cassandra.yaml",
|
||||
(stream) -> StreamUtils.copyToString(stream, StandardCharsets.UTF_8));
|
||||
String updatedConfig = config.replace("authenticator: AllowAllAuthenticator",
|
||||
"authenticator: PasswordAuthenticator");
|
||||
copyFileToContainer(Transferable.of(updatedConfig.getBytes(StandardCharsets.UTF_8)),
|
||||
"/etc/cassandra/cassandra.yaml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static final class CassandraWaitStrategy extends AbstractWaitStrategy {
|
||||
|
||||
@Override
|
||||
protected void waitUntilReady() {
|
||||
try {
|
||||
Unreliables.retryUntilSuccess((int) this.startupTimeout.getSeconds(), TimeUnit.SECONDS, () -> {
|
||||
getRateLimiter().doWhenReady(() -> cqlSessionBuilder().build());
|
||||
return true;
|
||||
});
|
||||
}
|
||||
catch (TimeoutException ex) {
|
||||
throw new ContainerLaunchException(
|
||||
"Timed out waiting for Cassandra to be accessible for query execution");
|
||||
}
|
||||
}
|
||||
|
||||
private CqlSessionBuilder cqlSessionBuilder() {
|
||||
return CqlSession.builder()
|
||||
.addContactPoint(new InetSocketAddress(this.waitStrategyTarget.getHost(),
|
||||
this.waitStrategyTarget.getFirstMappedPort()))
|
||||
.withLocalDatacenter("datacenter1")
|
||||
.withAuthCredentials("cassandra", "cassandra");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.couchbase;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import com.couchbase.client.core.diagnostics.ClusterState;
|
||||
import com.couchbase.client.core.diagnostics.DiagnosticsResult;
|
||||
import com.couchbase.client.java.Bucket;
|
||||
import com.couchbase.client.java.Cluster;
|
||||
import com.couchbase.client.java.Collection;
|
||||
import com.couchbase.client.java.env.ClusterEnvironment;
|
||||
import com.couchbase.client.java.json.JsonObject;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.couchbase.BucketDefinition;
|
||||
import org.testcontainers.couchbase.CouchbaseContainer;
|
||||
import org.testcontainers.couchbase.CouchbaseService;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link CouchbaseAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Brian Clozel
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class CouchbaseAutoConfigurationIntegrationTests {
|
||||
|
||||
private static final String BUCKET_NAME = "cbbucket";
|
||||
|
||||
@Container
|
||||
static final CouchbaseContainer couchbase = TestImage.container(CouchbaseContainer.class)
|
||||
.withEnabledServices(CouchbaseService.KV)
|
||||
.withCredentials("spring", "password")
|
||||
.withBucket(new BucketDefinition(BUCKET_NAME).withPrimaryIndex(false));
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(CouchbaseAutoConfiguration.class))
|
||||
.withPropertyValues("spring.couchbase.connection-string: " + couchbase.getConnectionString(),
|
||||
"spring.couchbase.username:spring", "spring.couchbase.password:password",
|
||||
"spring.couchbase.bucket.name:" + BUCKET_NAME, "spring.couchbase.env.timeouts.connect=2m",
|
||||
"spring.couchbase.env.timeouts.key-value=1m");
|
||||
|
||||
@Test
|
||||
void defaultConfiguration() {
|
||||
this.contextRunner.run((context) -> {
|
||||
assertThat(context).hasSingleBean(Cluster.class).hasSingleBean(ClusterEnvironment.class);
|
||||
Cluster cluster = context.getBean(Cluster.class);
|
||||
Bucket bucket = cluster.bucket(BUCKET_NAME);
|
||||
bucket.waitUntilReady(Duration.ofMinutes(5));
|
||||
DiagnosticsResult diagnostics = cluster.diagnostics();
|
||||
assertThat(diagnostics.state()).isEqualTo(ClusterState.ONLINE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenCouchbaseIsUsingCustomObjectMapperThenJsonCanBeRoundTripped() {
|
||||
this.contextRunner.withBean(ObjectMapper.class, ObjectMapper::new).run((context) -> {
|
||||
Cluster cluster = context.getBean(Cluster.class);
|
||||
Bucket bucket = cluster.bucket(BUCKET_NAME);
|
||||
bucket.waitUntilReady(Duration.ofMinutes(5));
|
||||
Collection collection = bucket.defaultCollection();
|
||||
collection.insert("test-document", JsonObject.create().put("a", "alpha"));
|
||||
assertThat(collection.get("test-document").contentAsObject().get("a")).isEqualTo("alpha");
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.cassandra;
|
||||
|
||||
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.containers.CassandraContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurationPackages;
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.cassandra.CassandraAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.cassandra.city.City;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.cassandra.config.SchemaAction;
|
||||
import org.springframework.data.cassandra.config.SessionFactoryFactoryBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link CassandraDataAutoConfiguration} that require a Cassandra instance.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class CassandraDataAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final CassandraContainer<?> cassandra = TestImage.container(CassandraContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(CassandraAutoConfiguration.class, CassandraDataAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"spring.cassandra.contact-points:" + cassandra.getHost() + ":" + cassandra.getFirstMappedPort(),
|
||||
"spring.cassandra.local-datacenter=datacenter1", "spring.cassandra.connection.connect-timeout=60s",
|
||||
"spring.cassandra.connection.init-query-timeout=60s", "spring.cassandra.request.timeout=60s")
|
||||
.withInitializer((context) -> AutoConfigurationPackages.register((BeanDefinitionRegistry) context,
|
||||
City.class.getPackage().getName()));
|
||||
|
||||
@Test
|
||||
void hasDefaultSchemaActionSet() {
|
||||
this.contextRunner.run((context) -> assertThat(context.getBean(SessionFactoryFactoryBean.class))
|
||||
.hasFieldOrPropertyWithValue("schemaAction", SchemaAction.NONE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void hasRecreateSchemaActionSet() {
|
||||
this.contextRunner.withUserConfiguration(KeyspaceTestConfiguration.class)
|
||||
.withPropertyValues("spring.cassandra.schemaAction=recreate_drop_unused")
|
||||
.run((context) -> assertThat(context.getBean(SessionFactoryFactoryBean.class))
|
||||
.hasFieldOrPropertyWithValue("schemaAction", SchemaAction.RECREATE_DROP_UNUSED));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class KeyspaceTestConfiguration {
|
||||
|
||||
@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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.elasticsearch;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.data.alt.elasticsearch.CityElasticsearchDbRepository;
|
||||
import org.springframework.boot.autoconfigure.data.elasticsearch.city.City;
|
||||
import org.springframework.boot.autoconfigure.data.elasticsearch.city.CityRepository;
|
||||
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchClientAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.config.EnableElasticsearchAuditing;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableElasticsearchRepositories;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ElasticsearchRepositoriesAutoConfiguration}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Brian Clozel
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ElasticsearchRepositoriesAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
static final ElasticsearchContainer elasticsearch = TestImage.container(ElasticsearchContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class,
|
||||
ElasticsearchClientAutoConfiguration.class, ElasticsearchRepositoriesAutoConfiguration.class,
|
||||
ElasticsearchDataAutoConfiguration.class))
|
||||
.withPropertyValues("spring.elasticsearch.uris=" + elasticsearch.getHttpHostAddress());
|
||||
|
||||
@Test
|
||||
void testDefaultRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(CityRepository.class)
|
||||
.hasSingleBean(ElasticsearchTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
|
||||
this.contextRunner.withUserConfiguration(CustomizedConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(CityElasticsearchDbRepository.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAuditingConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(AuditingConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ElasticsearchTemplate.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(EmptyDataPackage.class)
|
||||
static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(ElasticsearchRepositoriesAutoConfigurationTests.class)
|
||||
@EnableElasticsearchRepositories(basePackageClasses = CityElasticsearchDbRepository.class)
|
||||
static class CustomizedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(ElasticsearchRepositoriesAutoConfigurationTests.class)
|
||||
@EnableElasticsearchRepositories
|
||||
@EnableElasticsearchAuditing
|
||||
static class AuditingConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.elasticsearch;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.data.alt.elasticsearch.CityReactiveElasticsearchDbRepository;
|
||||
import org.springframework.boot.autoconfigure.data.elasticsearch.city.City;
|
||||
import org.springframework.boot.autoconfigure.data.elasticsearch.city.ReactiveCityRepository;
|
||||
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchClientAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ElasticsearchRestClientAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.elasticsearch.ReactiveElasticsearchClientAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.logging.ConditionEvaluationReportLoggingListener;
|
||||
import org.springframework.boot.logging.LogLevel;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchTemplate;
|
||||
import org.springframework.data.elasticsearch.config.EnableElasticsearchAuditing;
|
||||
import org.springframework.data.elasticsearch.repository.config.EnableReactiveElasticsearchRepositories;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link ReactiveElasticsearchRepositoriesAutoConfiguration}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Brian Clozel
|
||||
* @author Scott Frederick
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ReactiveElasticsearchRepositoriesAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
static final ElasticsearchContainer elasticsearch = TestImage.container(ElasticsearchContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchClientAutoConfiguration.class,
|
||||
ElasticsearchRestClientAutoConfiguration.class,
|
||||
ReactiveElasticsearchRepositoriesAutoConfiguration.class, ElasticsearchDataAutoConfiguration.class,
|
||||
ReactiveElasticsearchClientAutoConfiguration.class))
|
||||
.withPropertyValues(
|
||||
"spring.elasticsearch.uris=" + elasticsearch.getHost() + ":" + elasticsearch.getFirstMappedPort(),
|
||||
"spring.elasticsearch.socket-timeout=30s")
|
||||
.withInitializer(ConditionEvaluationReportLoggingListener.forLogLevel(LogLevel.INFO));
|
||||
|
||||
@Test
|
||||
void testDefaultRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(TestConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveCityRepository.class)
|
||||
.hasSingleBean(ReactiveElasticsearchTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoRepositoryConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(EmptyConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveElasticsearchTemplate.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
|
||||
this.contextRunner.withUserConfiguration(CustomizedConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(CityReactiveElasticsearchDbRepository.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAuditingConfiguration() {
|
||||
this.contextRunner.withUserConfiguration(AuditingConfiguration.class)
|
||||
.run((context) -> assertThat(context).hasSingleBean(ReactiveElasticsearchTemplate.class));
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(EmptyDataPackage.class)
|
||||
static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(ReactiveElasticsearchRepositoriesAutoConfigurationTests.class)
|
||||
@EnableReactiveElasticsearchRepositories(basePackageClasses = CityReactiveElasticsearchDbRepository.class)
|
||||
static class CustomizedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(ElasticsearchRepositoriesAutoConfigurationTests.class)
|
||||
@EnableReactiveElasticsearchRepositories
|
||||
@EnableElasticsearchAuditing
|
||||
static class AuditingConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.neo4j;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.Neo4jContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.neo4j.country.CountryRepository;
|
||||
import org.springframework.boot.autoconfigure.neo4j.Neo4jAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Test to ensure that the properties get read and applied during the auto-configuration.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
@SpringBootTest
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class Neo4jRepositoriesAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final Neo4jContainer<?> neo4j = TestImage.container(Neo4jContainer.class);
|
||||
|
||||
@DynamicPropertySource
|
||||
static void neo4jProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
|
||||
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
|
||||
registry.add("spring.neo4j.authentication.password", neo4j::getAdminPassword);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private CountryRepository countryRepository;
|
||||
|
||||
@Test
|
||||
void ensureRepositoryIsReady() {
|
||||
assertThat(this.countryRepository.count()).isZero();
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableNeo4jRepositories(basePackageClasses = CountryRepository.class)
|
||||
@ImportAutoConfiguration({ Neo4jAutoConfiguration.class, Neo4jDataAutoConfiguration.class,
|
||||
Neo4jRepositoriesAutoConfiguration.class })
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.data.redis;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.TestAutoConfigurationPackage;
|
||||
import org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.alt.redis.CityRedisRepository;
|
||||
import org.springframework.boot.autoconfigure.data.empty.EmptyDataPackage;
|
||||
import org.springframework.boot.autoconfigure.data.redis.city.City;
|
||||
import org.springframework.boot.autoconfigure.data.redis.city.CityRepository;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.boot.testsupport.container.RedisContainer;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.repository.configuration.EnableRedisRepositories;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Tests for {@link RedisRepositoriesAutoConfiguration}.
|
||||
*
|
||||
* @author Eddú Meléndez
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class RedisRepositoriesAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
public static RedisContainer redis = TestImage.container(RedisContainer.class);
|
||||
|
||||
private final AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
|
||||
|
||||
@BeforeEach
|
||||
void setUp() {
|
||||
TestPropertyValues
|
||||
.of("spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.applyTo(this.context.getEnvironment());
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void close() {
|
||||
this.context.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testDefaultRepositoryConfiguration() {
|
||||
this.context.register(TestConfiguration.class, RedisAutoConfiguration.class,
|
||||
RedisRepositoriesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(CityRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testNoRepositoryConfiguration() {
|
||||
this.context.register(EmptyConfiguration.class, RedisAutoConfiguration.class,
|
||||
RedisRepositoriesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean("redisTemplate")).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void doesNotTriggerDefaultRepositoryDetectionIfCustomized() {
|
||||
this.context.register(CustomizedConfiguration.class, RedisAutoConfiguration.class,
|
||||
RedisRepositoriesAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class);
|
||||
this.context.refresh();
|
||||
assertThat(this.context.getBean(CityRedisRepository.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(City.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(EmptyDataPackage.class)
|
||||
static class EmptyConfiguration {
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@TestAutoConfigurationPackage(RedisRepositoriesAutoConfigurationTests.class)
|
||||
@EnableRedisRepositories(basePackageClasses = CityRedisRepository.class)
|
||||
static class CustomizedConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.elasticsearch;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import co.elastic.clients.elasticsearch.ElasticsearchClient;
|
||||
import co.elastic.clients.elasticsearch.core.GetResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ElasticsearchClientAutoConfiguration}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ElasticsearchClientAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final ElasticsearchContainer elasticsearch = TestImage.container(ElasticsearchContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class,
|
||||
ElasticsearchRestClientAutoConfiguration.class, ElasticsearchClientAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void reactiveClientCanQueryElasticsearchNode() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.elasticsearch.uris=" + elasticsearch.getHttpHostAddress(),
|
||||
"spring.elasticsearch.connection-timeout=120s", "spring.elasticsearch.socket-timeout=120s")
|
||||
.run((context) -> {
|
||||
ElasticsearchClient client = context.getBean(ElasticsearchClient.class);
|
||||
client.index((b) -> b.index("foo").id("1").document(Map.of("a", "alpha", "b", "bravo")));
|
||||
GetResponse<Object> response = client.get((b) -> b.index("foo").id("1"), Object.class);
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.found()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.elasticsearch;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.elasticsearch.client.Request;
|
||||
import org.elasticsearch.client.Response;
|
||||
import org.elasticsearch.client.RestClient;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ElasticsearchRestClientAutoConfiguration}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Vedran Pavic
|
||||
* @author Evgeniy Cheban
|
||||
* @author Filip Hrisafov
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ElasticsearchRestClientAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final ElasticsearchContainer elasticsearch = TestImage.container(ElasticsearchContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(ElasticsearchRestClientAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void restClientCanQueryElasticsearchNode() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.elasticsearch.uris=" + elasticsearch.getHttpHostAddress(),
|
||||
"spring.elasticsearch.connection-timeout=120s", "spring.elasticsearch.socket-timeout=120s")
|
||||
.run((context) -> {
|
||||
RestClient client = context.getBean(RestClient.class);
|
||||
Request index = new Request("PUT", "/test/_doc/2");
|
||||
index.setJsonEntity("{" + " \"a\": \"alpha\"," + " \"b\": \"bravo\"" + "}");
|
||||
client.performRequest(index);
|
||||
Request getRequest = new Request("GET", "/test/_doc/2");
|
||||
Response response = client.performRequest(getRequest);
|
||||
try (InputStream input = response.getEntity().getContent()) {
|
||||
JsonNode result = new ObjectMapper().readTree(input);
|
||||
assertThat(result.path("found").asBoolean()).isTrue();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.elasticsearch;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import co.elastic.clients.elasticsearch.core.GetResponse;
|
||||
import co.elastic.clients.elasticsearch.core.IndexResponse;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.elasticsearch.ElasticsearchContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link ReactiveElasticsearchClientAutoConfiguration}.
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ReactiveElasticsearchClientAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final ElasticsearchContainer elasticsearch = TestImage.container(ElasticsearchContainer.class);
|
||||
|
||||
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
|
||||
.withConfiguration(AutoConfigurations.of(JacksonAutoConfiguration.class,
|
||||
ElasticsearchRestClientAutoConfiguration.class, ReactiveElasticsearchClientAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void reactiveClientCanQueryElasticsearchNode() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.elasticsearch.uris=" + elasticsearch.getHttpHostAddress(),
|
||||
"spring.elasticsearch.connection-timeout=120s", "spring.elasticsearch.socket-timeout=120s")
|
||||
.run((context) -> {
|
||||
ReactiveElasticsearchClient client = context.getBean(ReactiveElasticsearchClient.class);
|
||||
Mono<IndexResponse> index = client
|
||||
.index((b) -> b.index("foo").id("1").document(Map.of("a", "alpha", "b", "bravo")));
|
||||
index.block();
|
||||
Mono<GetResponse<Object>> get = client.get((b) -> b.index("foo").id("1"), Object.class);
|
||||
GetResponse<Object> response = get.block();
|
||||
assertThat(response).isNotNull();
|
||||
assertThat(response.found()).isTrue();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.neo4j;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.neo4j.driver.AuthToken;
|
||||
import org.neo4j.driver.AuthTokenManager;
|
||||
import org.neo4j.driver.AuthTokenManagers;
|
||||
import org.neo4j.driver.AuthTokens;
|
||||
import org.neo4j.driver.Driver;
|
||||
import org.neo4j.driver.Result;
|
||||
import org.neo4j.driver.Session;
|
||||
import org.neo4j.driver.Transaction;
|
||||
import org.testcontainers.containers.Neo4jContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link Neo4jAutoConfiguration}.
|
||||
*
|
||||
* @author Michael J. Simons
|
||||
* @author Stephane Nicoll
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class Neo4jAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
private static final Neo4jContainer<?> neo4j = TestImage.container(Neo4jContainer.class);
|
||||
|
||||
@SpringBootTest
|
||||
@Nested
|
||||
class DriverWithDefaultAuthToken {
|
||||
|
||||
@DynamicPropertySource
|
||||
static void neo4jProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
|
||||
registry.add("spring.neo4j.authentication.username", () -> "neo4j");
|
||||
registry.add("spring.neo4j.authentication.password", neo4j::getAdminPassword);
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private Driver driver;
|
||||
|
||||
@Test
|
||||
void driverCanHandleRequest() {
|
||||
try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) {
|
||||
Result statementResult = tx.run("MATCH (n:Thing) RETURN n LIMIT 1");
|
||||
assertThat(statementResult.hasNext()).isFalse();
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ImportAutoConfiguration(Neo4jAutoConfiguration.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SpringBootTest
|
||||
@Nested
|
||||
class DriverWithDynamicAuthToken {
|
||||
|
||||
@DynamicPropertySource
|
||||
static void neo4jProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
|
||||
registry.add("spring.neo4j.authentication.username", () -> "wrong");
|
||||
registry.add("spring.neo4j.authentication.password", () -> "alsowrong");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private Driver driver;
|
||||
|
||||
@Test
|
||||
void driverCanHandleRequest() {
|
||||
try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) {
|
||||
Result statementResult = tx.run("MATCH (n:Thing) RETURN n LIMIT 1");
|
||||
assertThat(statementResult.hasNext()).isFalse();
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ImportAutoConfiguration(Neo4jAutoConfiguration.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
AuthTokenManager authTokenManager() {
|
||||
return AuthTokenManagers.bearer(() -> AuthTokens.basic("neo4j", neo4j.getAdminPassword())
|
||||
.expiringAt(System.currentTimeMillis() + 5_000));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@SpringBootTest
|
||||
@Nested
|
||||
class DriverWithCustomConnectionDetailsIgnoresAuthTokenManager {
|
||||
|
||||
@DynamicPropertySource
|
||||
static void neo4jProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.neo4j.uri", neo4j::getBoltUrl);
|
||||
registry.add("spring.neo4j.authentication.username", () -> "wrong");
|
||||
registry.add("spring.neo4j.authentication.password", () -> "alsowrong");
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private Driver driver;
|
||||
|
||||
@Test
|
||||
void driverCanHandleRequest() {
|
||||
try (Session session = this.driver.session(); Transaction tx = session.beginTransaction()) {
|
||||
Result statementResult = tx.run("MATCH (n:Thing) RETURN n LIMIT 1");
|
||||
assertThat(statementResult.hasNext()).isFalse();
|
||||
tx.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ImportAutoConfiguration(Neo4jAutoConfiguration.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
@Bean
|
||||
AuthTokenManager authTokenManager() {
|
||||
return AuthTokenManagers.bearer(() -> AuthTokens.basic("wrongagain", "stillwrong")
|
||||
.expiringAt(System.currentTimeMillis() + 5_000));
|
||||
}
|
||||
|
||||
@Bean
|
||||
Neo4jConnectionDetails connectionDetails() {
|
||||
return new Neo4jConnectionDetails() {
|
||||
|
||||
@Override
|
||||
public URI getUri() {
|
||||
return URI.create(neo4j.getBoltUrl());
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthToken getAuthToken() {
|
||||
return AuthTokens.basic("neo4j", neo4j.getAdminPassword());
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.pulsar;
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.pulsar.client.api.PulsarClientException;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.PulsarContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.pulsar.annotation.PulsarListener;
|
||||
import org.springframework.pulsar.core.PulsarTemplate;
|
||||
import org.springframework.test.context.DynamicPropertyRegistry;
|
||||
import org.springframework.test.context.DynamicPropertySource;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link PulsarAutoConfiguration}.
|
||||
*
|
||||
* @author Chris Bono
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class PulsarAutoConfigurationIntegrationTests {
|
||||
|
||||
@Container
|
||||
static final PulsarContainer pulsar = TestImage.container(PulsarContainer.class);
|
||||
|
||||
private static final CountDownLatch listenLatch = new CountDownLatch(1);
|
||||
|
||||
private static final String TOPIC = "pacit-hello-topic";
|
||||
|
||||
@DynamicPropertySource
|
||||
static void pulsarProperties(DynamicPropertyRegistry registry) {
|
||||
registry.add("spring.pulsar.client.service-url", pulsar::getPulsarBrokerUrl);
|
||||
registry.add("spring.pulsar.admin.service-url", pulsar::getHttpServiceUrl);
|
||||
}
|
||||
|
||||
@Test
|
||||
void appStartsWithAutoConfiguredSpringPulsarComponents(
|
||||
@Autowired(required = false) PulsarTemplate<String> pulsarTemplate) {
|
||||
assertThat(pulsarTemplate).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void templateCanBeAccessedDuringWebRequest(@Autowired TestRestTemplate restTemplate) throws InterruptedException {
|
||||
assertThat(restTemplate.getForObject("/hello", String.class)).startsWith("Hello World -> ");
|
||||
assertThat(listenLatch.await(5, TimeUnit.SECONDS)).isTrue();
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
@ImportAutoConfiguration({ DispatcherServletAutoConfiguration.class, ServletWebServerFactoryAutoConfiguration.class,
|
||||
WebMvcAutoConfiguration.class, HttpMessageConvertersAutoConfiguration.class, JacksonAutoConfiguration.class,
|
||||
PulsarAutoConfiguration.class, PulsarReactiveAutoConfiguration.class })
|
||||
@Import(TestWebController.class)
|
||||
static class TestConfiguration {
|
||||
|
||||
@PulsarListener(subscriptionName = TOPIC + "-sub", topics = TOPIC)
|
||||
void listen(String ignored) {
|
||||
listenLatch.countDown();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@RestController
|
||||
static class TestWebController {
|
||||
|
||||
private final PulsarTemplate<String> pulsarTemplate;
|
||||
|
||||
TestWebController(PulsarTemplate<String> pulsarTemplate) {
|
||||
this.pulsarTemplate = pulsarTemplate;
|
||||
}
|
||||
|
||||
@GetMapping("/hello")
|
||||
String sayHello() throws PulsarClientException {
|
||||
return "Hello World -> " + this.pulsarTemplate.send(TOPIC, "hello");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.mongo.MongoReactiveDataAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoReactiveAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
|
||||
import org.springframework.session.data.redis.ReactiveRedisSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Mongo-specific tests for {@link SessionAutoConfiguration}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @author Weix Sun
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ReactiveSessionAutoConfigurationMongoTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
static final MongoDBContainer mongoDb = TestImage.container(MongoDBContainer.class);
|
||||
|
||||
private final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(ReactiveRedisSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class, MongoAutoConfiguration.class,
|
||||
MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
|
||||
MongoReactiveDataAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
this.contextRunner.withPropertyValues("spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl())
|
||||
.run(validateSpringSessionUsesMongo("sessions"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomTimeout() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.timeout=1m", "spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl())
|
||||
.run((context) -> {
|
||||
ReactiveMongoSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveMongoSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", Duration.ofMinutes(1));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomSessionTimeout() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("server.reactive.session.timeout=1m",
|
||||
"spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl())
|
||||
.run((context) -> {
|
||||
ReactiveMongoSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveMongoSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", Duration.ofMinutes(1));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void mongoSessionStoreWithCustomizations() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.mongodb.collection-name=foo",
|
||||
"spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl())
|
||||
.run(validateSpringSessionUsesMongo("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sessionCookieConfigurationIsAppliedToAutoConfiguredWebSessionIdResolver() {
|
||||
AutoConfigurations autoConfigurations = AutoConfigurations.of(SessionAutoConfiguration.class,
|
||||
MongoAutoConfiguration.class, MongoDataAutoConfiguration.class, MongoReactiveAutoConfiguration.class,
|
||||
MongoReactiveDataAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class);
|
||||
new ReactiveWebApplicationContextRunner().withConfiguration(autoConfigurations)
|
||||
.withUserConfiguration(Config.class)
|
||||
.withClassLoader(new FilteredClassLoader(ReactiveRedisSessionRepository.class))
|
||||
.withPropertyValues("server.reactive.session.cookie.name:JSESSIONID",
|
||||
"server.reactive.session.cookie.domain:.example.com",
|
||||
"server.reactive.session.cookie.path:/example", "server.reactive.session.cookie.max-age:60",
|
||||
"server.reactive.session.cookie.http-only:false", "server.reactive.session.cookie.secure:false",
|
||||
"server.reactive.session.cookie.same-site:strict",
|
||||
"spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl())
|
||||
.run(assertExchangeWithSession((exchange) -> {
|
||||
List<ResponseCookie> cookies = exchange.getResponse().getCookies().get("JSESSIONID");
|
||||
assertThat(cookies).isNotEmpty();
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getDomain().equals(".example.com"));
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getPath().equals("/example"));
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getMaxAge().equals(Duration.ofSeconds(60)));
|
||||
assertThat(cookies).allMatch((cookie) -> !cookie.isHttpOnly());
|
||||
assertThat(cookies).allMatch((cookie) -> !cookie.isSecure());
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getSameSite().equals("Strict"));
|
||||
}));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableReactiveWebApplicationContext> validateSpringSessionUsesMongo(
|
||||
String collectionName) {
|
||||
return (context) -> {
|
||||
ReactiveMongoSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveMongoSessionRepository.class);
|
||||
assertThat(repository.getCollectionName()).isEqualTo(collectionName);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.reactive.WebSessionIdResolverAutoConfiguration;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableReactiveWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.RedisContainer;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.http.ResponseCookie;
|
||||
import org.springframework.session.MapSession;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.data.mongo.ReactiveMongoSessionRepository;
|
||||
import org.springframework.session.data.redis.ReactiveRedisSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Reactive Redis-specific tests for {@link SessionAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
* @author Vedran Pavic
|
||||
* @author Weix Sun
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class ReactiveSessionAutoConfigurationRedisTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
public static RedisContainer redis = TestImage.container(RedisContainer.class);
|
||||
|
||||
protected final ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(ReactiveMongoSessionRepository.class))
|
||||
.withConfiguration(
|
||||
AutoConfigurations.of(SessionAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
this.contextRunner.run(validateSpringSessionUsesRedis("spring:session:", SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void redisTakesPrecedenceMultipleImplementations() {
|
||||
ReactiveWebApplicationContextRunner contextRunner = new ReactiveWebApplicationContextRunner().withConfiguration(
|
||||
AutoConfigurations.of(SessionAutoConfiguration.class, WebSessionIdResolverAutoConfiguration.class,
|
||||
RedisAutoConfiguration.class, RedisReactiveAutoConfiguration.class));
|
||||
contextRunner.run(validateSpringSessionUsesRedis("spring:session:", SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomTimeout() {
|
||||
this.contextRunner.withPropertyValues("spring.session.timeout=1m").run((context) -> {
|
||||
ReactiveRedisSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveRedisSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", Duration.ofMinutes(1));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomWebFluxTimeout() {
|
||||
this.contextRunner.withPropertyValues("server.reactive.session.timeout=1m").run((context) -> {
|
||||
ReactiveRedisSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveRedisSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", Duration.ofMinutes(1));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void redisSessionStoreWithCustomizations() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.namespace=foo", "spring.session.redis.save-mode=on-get-attribute")
|
||||
.run(validateSpringSessionUsesRedis("foo:", SaveMode.ON_GET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void sessionCookieConfigurationIsAppliedToAutoConfiguredWebSessionIdResolver() {
|
||||
this.contextRunner.withUserConfiguration(Config.class)
|
||||
.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort(),
|
||||
"server.reactive.session.cookie.name:JSESSIONID",
|
||||
"server.reactive.session.cookie.domain:.example.com",
|
||||
"server.reactive.session.cookie.path:/example", "server.reactive.session.cookie.max-age:60",
|
||||
"server.reactive.session.cookie.http-only:false", "server.reactive.session.cookie.secure:false",
|
||||
"server.reactive.session.cookie.same-site:strict")
|
||||
.run(assertExchangeWithSession((exchange) -> {
|
||||
List<ResponseCookie> cookies = exchange.getResponse().getCookies().get("JSESSIONID");
|
||||
assertThat(cookies).isNotEmpty();
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getDomain().equals(".example.com"));
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getPath().equals("/example"));
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getMaxAge().equals(Duration.ofSeconds(60)));
|
||||
assertThat(cookies).allMatch((cookie) -> !cookie.isHttpOnly());
|
||||
assertThat(cookies).allMatch((cookie) -> !cookie.isSecure());
|
||||
assertThat(cookies).allMatch((cookie) -> cookie.getSameSite().equals("Strict"));
|
||||
}));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableReactiveWebApplicationContext> validateSpringSessionUsesRedis(String namespace,
|
||||
SaveMode saveMode) {
|
||||
return (context) -> {
|
||||
ReactiveRedisSessionRepository repository = validateSessionRepository(context,
|
||||
ReactiveRedisSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
MapSession.DEFAULT_MAX_INACTIVE_INTERVAL);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("namespace", namespace);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("saveMode", saveMode);
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
|
||||
import java.time.Duration;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.containers.MongoDBContainer;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
/**
|
||||
* Mongo-specific tests for {@link SessionAutoConfiguration}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class SessionAutoConfigurationMongoTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
static final MongoDBContainer mongoDb = TestImage.container(MongoDBContainer.class);
|
||||
|
||||
private final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(HazelcastIndexedSessionRepository.class,
|
||||
JdbcIndexedSessionRepository.class, RedisIndexedSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(MongoAutoConfiguration.class, MongoDataAutoConfiguration.class,
|
||||
SessionAutoConfiguration.class))
|
||||
.withPropertyValues("spring.data.mongodb.uri=" + mongoDb.getReplicaSetUrl());
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
this.contextRunner.run(validateSpringSessionUsesMongo("sessions"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomTimeout() {
|
||||
this.contextRunner.withPropertyValues("spring.session.timeout=1m")
|
||||
.run(validateSpringSessionUsesMongo("sessions", Duration.ofMinutes(1)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void mongoSessionStoreWithCustomizations() {
|
||||
this.contextRunner.withPropertyValues("spring.session.mongodb.collection-name=foo")
|
||||
.run(validateSpringSessionUsesMongo("foo"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() {
|
||||
this.contextRunner.withUserConfiguration(CustomizerConfiguration.class)
|
||||
.withPropertyValues("spring.session.mongodb.collection-name=foo")
|
||||
.run(validateSpringSessionUsesMongo("customized"));
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesMongo(String collectionName) {
|
||||
return validateSpringSessionUsesMongo(collectionName,
|
||||
new ServerProperties().getServlet().getSession().getTimeout());
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesMongo(String collectionName,
|
||||
Duration timeout) {
|
||||
return (context) -> {
|
||||
MongoIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
MongoIndexedSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("collectionName", collectionName);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", timeout);
|
||||
};
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomizerConfiguration {
|
||||
|
||||
@Bean
|
||||
SessionRepositoryCustomizer<MongoIndexedSessionRepository> sessionRepositoryCustomizer() {
|
||||
return (repository) -> repository.setCollectionName("customized");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,265 @@
|
||||
/*
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.autoconfigure.session;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfigurations;
|
||||
import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.web.ServerProperties;
|
||||
import org.springframework.boot.context.properties.source.InvalidConfigurationPropertyValueException;
|
||||
import org.springframework.boot.test.context.FilteredClassLoader;
|
||||
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
|
||||
import org.springframework.boot.test.context.runner.ContextConsumer;
|
||||
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
|
||||
import org.springframework.boot.testsupport.container.RedisContainer;
|
||||
import org.springframework.boot.testsupport.container.TestImage;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.redis.connection.RedisConnection;
|
||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||
import org.springframework.session.FlushMode;
|
||||
import org.springframework.session.SaveMode;
|
||||
import org.springframework.session.config.SessionRepositoryCustomizer;
|
||||
import org.springframework.session.data.mongo.MongoIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisIndexedSessionRepository;
|
||||
import org.springframework.session.data.redis.RedisSessionRepository;
|
||||
import org.springframework.session.data.redis.config.ConfigureNotifyKeyspaceEventsAction;
|
||||
import org.springframework.session.data.redis.config.ConfigureRedisAction;
|
||||
import org.springframework.session.hazelcast.HazelcastIndexedSessionRepository;
|
||||
import org.springframework.session.jdbc.JdbcIndexedSessionRepository;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.entry;
|
||||
|
||||
/**
|
||||
* Redis specific tests for {@link SessionAutoConfiguration}.
|
||||
*
|
||||
* @author Stephane Nicoll
|
||||
* @author Vedran Pavic
|
||||
*/
|
||||
@Testcontainers(disabledWithoutDocker = true)
|
||||
class SessionAutoConfigurationRedisTests extends AbstractSessionAutoConfigurationTests {
|
||||
|
||||
@Container
|
||||
public static RedisContainer redis = TestImage.container(RedisContainer.class);
|
||||
|
||||
protected final WebApplicationContextRunner contextRunner = new WebApplicationContextRunner()
|
||||
.withClassLoader(new FilteredClassLoader(HazelcastIndexedSessionRepository.class,
|
||||
JdbcIndexedSessionRepository.class, MongoIndexedSessionRepository.class))
|
||||
.withConfiguration(AutoConfigurations.of(SessionAutoConfiguration.class));
|
||||
|
||||
@Test
|
||||
void defaultConfig() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.run(validateSpringSessionUsesDefaultRedis("spring:session:", FlushMode.ON_SAVE,
|
||||
SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void invalidConfigurationPropertyValueWhenDefaultConfigIsUsedWithCustomCronCleanup() {
|
||||
this.contextRunner.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort(), "spring.session.redis.cleanup-cron=0 0 * * * *")
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
assertThat(context).hasFailed();
|
||||
assertThat(context.getStartupFailure())
|
||||
.hasRootCauseExactlyInstanceOf(InvalidConfigurationPropertyValueException.class);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void redisTakesPrecedenceMultipleImplementations() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateSpringSessionUsesDefaultRedis("spring:session:", FlushMode.ON_SAVE,
|
||||
SaveMode.ON_SET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultConfigWithCustomTimeout() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort(), "spring.session.timeout=1m")
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.run((context) -> {
|
||||
RedisSessionRepository repository = validateSessionRepository(context, RedisSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval", Duration.ofMinutes(1));
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void defaultRedisSessionStoreWithCustomizations() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withPropertyValues("spring.session.redis.namespace=foo", "spring.session.redis.flush-mode=immediate",
|
||||
"spring.session.redis.save-mode=on-get-attribute", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateSpringSessionUsesDefaultRedis("foo:", FlushMode.IMMEDIATE, SaveMode.ON_GET_ATTRIBUTE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionDefaultConfig() {
|
||||
this.contextRunner
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.run(validateSpringSessionUsesIndexedRedis("spring:session:", FlushMode.ON_SAVE, SaveMode.ON_SET_ATTRIBUTE,
|
||||
"0 * * * * *"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionStoreWithCustomizations() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed", "spring.session.redis.namespace=foo",
|
||||
"spring.session.redis.flush-mode=immediate", "spring.session.redis.save-mode=on-get-attribute",
|
||||
"spring.session.redis.cleanup-cron=0 0 12 * * *", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateSpringSessionUsesIndexedRedis("foo:", FlushMode.IMMEDIATE, SaveMode.ON_GET_ATTRIBUTE,
|
||||
"0 0 12 * * *"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithConfigureActionNone() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.session.redis.configure-action=none", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateStrategy(ConfigureRedisAction.NO_OP.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithDefaultConfigureActionNone() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateStrategy(ConfigureNotifyKeyspaceEventsAction.class, entry("notify-keyspace-events", "gxE")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexedRedisSessionWithCustomConfigureRedisActionBean() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withUserConfiguration(MaxEntriesRedisAction.class)
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run(validateStrategy(MaxEntriesRedisAction.class, entry("set-max-intset-entries", "1024")));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withUserConfiguration(CustomizerConfiguration.class)
|
||||
.withPropertyValues("spring.session.redis.flush-mode=immediate",
|
||||
"spring.data.redis.host=" + redis.getHost(), "spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run((context) -> {
|
||||
RedisSessionRepository repository = validateSessionRepository(context, RedisSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("flushMode", FlushMode.ON_SAVE);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
void whenIndexedAndTheUserDefinesTheirOwnSessionRepositoryCustomizerThenDefaultConfigurationIsOverwritten() {
|
||||
this.contextRunner.withConfiguration(AutoConfigurations.of(RedisAutoConfiguration.class))
|
||||
.withUserConfiguration(IndexedCustomizerConfiguration.class)
|
||||
.withPropertyValues("spring.session.redis.repository-type=indexed",
|
||||
"spring.session.redis.flush-mode=immediate", "spring.data.redis.host=" + redis.getHost(),
|
||||
"spring.data.redis.port=" + redis.getFirstMappedPort())
|
||||
.run((context) -> {
|
||||
RedisIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
RedisIndexedSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("flushMode", FlushMode.ON_SAVE);
|
||||
});
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesDefaultRedis(String keyNamespace,
|
||||
FlushMode flushMode, SaveMode saveMode) {
|
||||
return (context) -> {
|
||||
RedisSessionRepository repository = validateSessionRepository(context, RedisSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
new ServerProperties().getServlet().getSession().getTimeout());
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("keyNamespace", keyNamespace);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("flushMode", flushMode);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("saveMode", saveMode);
|
||||
};
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableWebApplicationContext> validateSpringSessionUsesIndexedRedis(String keyNamespace,
|
||||
FlushMode flushMode, SaveMode saveMode, String cleanupCron) {
|
||||
return (context) -> {
|
||||
RedisIndexedSessionRepository repository = validateSessionRepository(context,
|
||||
RedisIndexedSessionRepository.class);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("defaultMaxInactiveInterval",
|
||||
new ServerProperties().getServlet().getSession().getTimeout());
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("namespace", keyNamespace);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("flushMode", flushMode);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("saveMode", saveMode);
|
||||
assertThat(repository).hasFieldOrPropertyWithValue("cleanupCron", cleanupCron);
|
||||
};
|
||||
}
|
||||
|
||||
private ContextConsumer<AssertableWebApplicationContext> validateStrategy(
|
||||
Class<? extends ConfigureRedisAction> expectedConfigureRedisActionType, Map.Entry<?, ?>... expectedConfig) {
|
||||
return (context) -> {
|
||||
assertThat(context).hasSingleBean(ConfigureRedisAction.class);
|
||||
assertThat(context).hasSingleBean(RedisConnectionFactory.class);
|
||||
assertThat(context.getBean(ConfigureRedisAction.class)).isInstanceOf(expectedConfigureRedisActionType);
|
||||
RedisConnection connection = context.getBean(RedisConnectionFactory.class).getConnection();
|
||||
if (expectedConfig.length > 0) {
|
||||
assertThat(connection.serverCommands().getConfig("*")).contains(expectedConfig);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static class MaxEntriesRedisAction implements ConfigureRedisAction {
|
||||
|
||||
@Override
|
||||
public void configure(RedisConnection connection) {
|
||||
connection.serverCommands().setConfig("set-max-intset-entries", "1024");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class CustomizerConfiguration {
|
||||
|
||||
@Bean
|
||||
SessionRepositoryCustomizer<RedisSessionRepository> sessionRepositoryCustomizer() {
|
||||
return (repository) -> repository.setFlushMode(FlushMode.ON_SAVE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class IndexedCustomizerConfiguration {
|
||||
|
||||
@Bean
|
||||
SessionRepositoryCustomizer<RedisIndexedSessionRepository> sessionRepositoryCustomizer() {
|
||||
return (repository) -> repository.setFlushMode(FlushMode.ON_SAVE);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user