diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java index 69a261920a..12f26f2caf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfiguration.java @@ -16,6 +16,8 @@ package org.springframework.boot.autoconfigure.mongo; +import java.util.stream.Collectors; + import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClient; @@ -36,6 +38,7 @@ import org.springframework.core.env.Environment; * @author Phillip Webb * @author Mark Paluch * @author Stephane Nicoll + * @author Scott Frederick * @since 1.0.0 */ @Configuration(proxyBeanMethods = false) @@ -46,9 +49,12 @@ public class MongoAutoConfiguration { @Bean @ConditionalOnMissingBean(MongoClient.class) - public MongoClient mongo(MongoProperties properties, ObjectProvider settings, - Environment environment) { - return new MongoClientFactory(properties, environment).createMongoClient(settings.getIfAvailable()); + public MongoClient mongo(MongoProperties properties, Environment environment, + ObjectProvider builderCustomizers, + ObjectProvider settings) { + return new MongoClientFactory(properties, environment, + builderCustomizers.orderedStream().collect(Collectors.toList())) + .createMongoClient(settings.getIfAvailable()); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java index 5e58435046..60c775d0cf 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactory.java @@ -16,21 +16,15 @@ package org.springframework.boot.autoconfigure.mongo; -import java.util.Collections; import java.util.List; -import com.mongodb.ConnectionString; -import com.mongodb.MongoClientSettings; -import com.mongodb.MongoClientSettings.Builder; -import com.mongodb.MongoCredential; -import com.mongodb.ServerAddress; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import org.springframework.core.env.Environment; /** - * A factory for a blocking {@link MongoClient} that applies {@link MongoProperties}. + * A factory for a blocking {@link MongoClient}. * * @author Dave Syer * @author Phillip Webb @@ -40,90 +34,32 @@ import org.springframework.core.env.Environment; * @author Stephane Nicoll * @author Nasko Vasilev * @author Mark Paluch + * @author Scott Frederick * @since 2.0.0 */ -public class MongoClientFactory { - - private final MongoProperties properties; - - private final Environment environment; +public class MongoClientFactory extends MongoClientFactorySupport { + /** + * Construct a factory for creating a blocking {@link MongoClient}. + * @param properties configuration properties + * @param environment a Spring {@link Environment} containing configuration properties + * @deprecated since 2.3.0 in favor of + * {@link #MongoClientFactory(MongoProperties, Environment, List)} + */ + @Deprecated public MongoClientFactory(MongoProperties properties, Environment environment) { - this.properties = properties; - this.environment = environment; + this(properties, environment, null); } /** - * Creates a {@link MongoClient} using the given {@link MongoClientSettings settings}. - * If the environment contains a {@code local.mongo.port} property, it is used to - * configure a client to an embedded MongoDB instance. - * @param settings the settings - * @return the Mongo client + * Construct a factory for creating a blocking {@link MongoClient}. + * @param properties configuration properties + * @param environment a Spring {@link Environment} containing configuration properties + * @param builderCustomizers a list of configuration settings customizers */ - public MongoClient createMongoClient(MongoClientSettings settings) { - Builder settingsBuilder = (settings != null) ? MongoClientSettings.builder(settings) - : MongoClientSettings.builder(); - settingsBuilder.uuidRepresentation(this.properties.getUuidRepresentation()); - Integer embeddedPort = getEmbeddedPort(); - if (embeddedPort != null) { - return createEmbeddedMongoClient(settingsBuilder, embeddedPort); - } - return createNetworkMongoClient(settingsBuilder); - } - - private Integer getEmbeddedPort() { - if (this.environment != null) { - String localPort = this.environment.getProperty("local.mongo.port"); - if (localPort != null) { - return Integer.valueOf(localPort); - } - } - return null; - } - - private MongoClient createEmbeddedMongoClient(Builder settings, int port) { - String host = (this.properties.getHost() != null) ? this.properties.getHost() : "localhost"; - settings.applyToClusterSettings( - (cluster) -> cluster.hosts(Collections.singletonList(new ServerAddress(host, port)))); - return MongoClients.create(settings.build()); - } - - private MongoClient createNetworkMongoClient(Builder settings) { - MongoProperties properties = this.properties; - if (properties.getUri() != null) { - return createMongoClient(properties.getUri(), settings); - } - if (hasCustomAddress() || hasCustomCredentials()) { - if (hasCustomCredentials()) { - String database = (this.properties.getAuthenticationDatabase() != null) - ? this.properties.getAuthenticationDatabase() : this.properties.getMongoClientDatabase(); - settings.credential((MongoCredential.createCredential(this.properties.getUsername(), database, - this.properties.getPassword()))); - } - String host = getValue(properties.getHost(), "localhost"); - int port = getValue(properties.getPort(), MongoProperties.DEFAULT_PORT); - List seeds = Collections.singletonList(new ServerAddress(host, port)); - settings.applyToClusterSettings((cluster) -> cluster.hosts(seeds)); - return MongoClients.create(settings.build()); - } - return createMongoClient(MongoProperties.DEFAULT_URI, settings); - } - - private MongoClient createMongoClient(String uri, Builder settings) { - settings.applyConnectionString(new ConnectionString(uri)); - return MongoClients.create(settings.build()); - } - - private T getValue(T value, T fallback) { - return (value != null) ? value : fallback; - } - - private boolean hasCustomAddress() { - return this.properties.getHost() != null || this.properties.getPort() != null; - } - - private boolean hasCustomCredentials() { - return this.properties.getUsername() != null && this.properties.getPassword() != null; + public MongoClientFactory(MongoProperties properties, Environment environment, + List builderCustomizers) { + super(properties, environment, builderCustomizers, MongoClients::create); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupport.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupport.java new file mode 100644 index 0000000000..a990015733 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupport.java @@ -0,0 +1,149 @@ +/* + * Copyright 2012-2020 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.mongo; + +import java.util.Collections; +import java.util.List; +import java.util.function.BiFunction; + +import com.mongodb.ConnectionString; +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoClientSettings.Builder; +import com.mongodb.MongoCredential; +import com.mongodb.MongoDriverInformation; +import com.mongodb.ServerAddress; + +import org.springframework.core.env.Environment; +import org.springframework.util.Assert; + +/** + * Base class for setup that is common to MongoDB client factories. + * + * @author Christoph Strobl + * @author Scott Frederick + * @since 2.3.0 + */ +public abstract class MongoClientFactorySupport { + + private final MongoProperties properties; + + private final Environment environment; + + private final List builderCustomizers; + + private final BiFunction clientCreator; + + protected MongoClientFactorySupport(MongoProperties properties, Environment environment, + List builderCustomizers, + BiFunction clientCreator) { + this.properties = properties; + this.environment = environment; + this.builderCustomizers = (builderCustomizers != null) ? builderCustomizers : Collections.emptyList(); + this.clientCreator = clientCreator; + } + + public T createMongoClient(MongoClientSettings settings) { + MongoClientSettings targetSettings = computeClientSettings(settings); + return this.clientCreator.apply(targetSettings, driverInformation()); + } + + private MongoClientSettings computeClientSettings(MongoClientSettings settings) { + Builder settingsBuilder = (settings != null) ? MongoClientSettings.builder(settings) + : MongoClientSettings.builder(); + validateConfiguration(); + applyUuidRepresentation(settingsBuilder); + applyHostAndPort(settingsBuilder); + applyCredentials(settingsBuilder); + customize(settingsBuilder); + return settingsBuilder.build(); + } + + private void validateConfiguration() { + if (hasCustomAddress() || hasCustomCredentials()) { + Assert.state(this.properties.getUri() == null, + "Invalid mongo configuration, either uri or host/port/credentials must be specified"); + } + } + + private void applyUuidRepresentation(Builder settingsBuilder) { + settingsBuilder.uuidRepresentation(this.properties.getUuidRepresentation()); + } + + private void applyHostAndPort(MongoClientSettings.Builder settings) { + if (isEmbedded()) { + settings.applyConnectionString(new ConnectionString("mongodb://localhost:" + getEmbeddedPort())); + return; + } + + if (hasCustomAddress()) { + String host = getOrDefault(this.properties.getHost(), "localhost"); + int port = getOrDefault(this.properties.getPort(), MongoProperties.DEFAULT_PORT); + ServerAddress serverAddress = new ServerAddress(host, port); + settings.applyToClusterSettings((cluster) -> cluster.hosts(Collections.singletonList(serverAddress))); + return; + } + + settings.applyConnectionString(new ConnectionString(this.properties.determineUri())); + } + + private void applyCredentials(Builder builder) { + if (hasCustomCredentials()) { + String database = (this.properties.getAuthenticationDatabase() != null) + ? this.properties.getAuthenticationDatabase() : this.properties.getMongoClientDatabase(); + builder.credential((MongoCredential.createCredential(this.properties.getUsername(), database, + this.properties.getPassword()))); + } + } + + private void customize(MongoClientSettings.Builder builder) { + for (MongoClientSettingsBuilderCustomizer customizer : this.builderCustomizers) { + customizer.customize(builder); + } + } + + private V getOrDefault(V value, V defaultValue) { + return (value != null) ? value : defaultValue; + } + + private Integer getEmbeddedPort() { + if (this.environment != null) { + String localPort = this.environment.getProperty("local.mongo.port"); + if (localPort != null) { + return Integer.valueOf(localPort); + } + } + return null; + } + + private boolean isEmbedded() { + return getEmbeddedPort() != null; + } + + private boolean hasCustomCredentials() { + return this.properties.getUsername() != null && this.properties.getPassword() != null; + } + + private boolean hasCustomAddress() { + return this.properties.getHost() != null || this.properties.getPort() != null; + } + + private MongoDriverInformation driverInformation() { + return MongoDriverInformation.builder(MongoDriverInformation.builder().build()).driverName("spring-boot") + .build(); + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java index e1e83c74b6..3c04855451 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactory.java @@ -16,137 +16,26 @@ package org.springframework.boot.autoconfigure.mongo; -import java.util.Collections; import java.util.List; -import com.mongodb.ConnectionString; -import com.mongodb.MongoClientSettings; -import com.mongodb.MongoClientSettings.Builder; -import com.mongodb.MongoCredential; -import com.mongodb.ServerAddress; import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoClients; import org.springframework.core.env.Environment; -import org.springframework.util.Assert; /** - * A factory for a reactive {@link MongoClient} that applies {@link MongoProperties}. + * A factory for a reactive {@link MongoClient}. * * @author Mark Paluch * @author Stephane Nicoll + * @author Scott Frederick * @since 2.0.0 */ -public class ReactiveMongoClientFactory { - - private final MongoProperties properties; - - private final Environment environment; - - private final List builderCustomizers; +public class ReactiveMongoClientFactory extends MongoClientFactorySupport { public ReactiveMongoClientFactory(MongoProperties properties, Environment environment, List builderCustomizers) { - this.properties = properties; - this.environment = environment; - this.builderCustomizers = (builderCustomizers != null) ? builderCustomizers : Collections.emptyList(); - } - - /** - * Creates a {@link MongoClient} using the given {@code settings}. If the environment - * contains a {@code local.mongo.port} property, it is used to configure a client to - * an embedded MongoDB instance. - * @param settings the settings - * @return the Mongo client - */ - public MongoClient createMongoClient(MongoClientSettings settings) { - Integer embeddedPort = getEmbeddedPort(); - if (embeddedPort != null) { - return createEmbeddedMongoClient(settings, embeddedPort); - } - return createNetworkMongoClient(settings); - } - - private Integer getEmbeddedPort() { - if (this.environment != null) { - String localPort = this.environment.getProperty("local.mongo.port"); - if (localPort != null) { - return Integer.valueOf(localPort); - } - } - return null; - } - - private MongoClient createEmbeddedMongoClient(MongoClientSettings settings, int port) { - Builder builder = builder(settings); - String host = (this.properties.getHost() != null) ? this.properties.getHost() : "localhost"; - builder.applyToClusterSettings( - (cluster) -> cluster.hosts(Collections.singletonList(new ServerAddress(host, port)))); - return createMongoClient(builder); - } - - private MongoClient createNetworkMongoClient(MongoClientSettings settings) { - if (hasCustomAddress() || hasCustomCredentials()) { - return createCredentialNetworkMongoClient(settings); - } - ConnectionString connectionString = new ConnectionString(this.properties.determineUri()); - return createMongoClient(createBuilder(settings, connectionString)); - } - - private MongoClient createCredentialNetworkMongoClient(MongoClientSettings settings) { - Assert.state(this.properties.getUri() == null, - "Invalid mongo configuration, either uri or host/port/credentials must be specified"); - Builder builder = builder(settings); - if (hasCustomCredentials()) { - applyCredentials(builder); - } - String host = getOrDefault(this.properties.getHost(), "localhost"); - int port = getOrDefault(this.properties.getPort(), MongoProperties.DEFAULT_PORT); - ServerAddress serverAddress = new ServerAddress(host, port); - builder.applyToClusterSettings((cluster) -> cluster.hosts(Collections.singletonList(serverAddress))); - return createMongoClient(builder); - } - - private void applyCredentials(Builder builder) { - String database = (this.properties.getAuthenticationDatabase() != null) - ? this.properties.getAuthenticationDatabase() : this.properties.getMongoClientDatabase(); - builder.credential((MongoCredential.createCredential(this.properties.getUsername(), database, - this.properties.getPassword()))); - } - - private T getOrDefault(T value, T defaultValue) { - return (value != null) ? value : defaultValue; - } - - private MongoClient createMongoClient(Builder builder) { - builder.uuidRepresentation(this.properties.getUuidRepresentation()); - customize(builder); - return MongoClients.create(builder.build()); - } - - private Builder createBuilder(MongoClientSettings settings, ConnectionString connection) { - return builder(settings).applyConnectionString(connection); - } - - private void customize(MongoClientSettings.Builder builder) { - for (MongoClientSettingsBuilderCustomizer customizer : this.builderCustomizers) { - customizer.customize(builder); - } - } - - private boolean hasCustomAddress() { - return this.properties.getHost() != null || this.properties.getPort() != null; - } - - private boolean hasCustomCredentials() { - return this.properties.getUsername() != null && this.properties.getPassword() != null; - } - - private Builder builder(MongoClientSettings settings) { - if (settings == null) { - return MongoClientSettings.builder(); - } - return MongoClientSettings.builder(settings); + super(properties, environment, builderCustomizers, MongoClients::create); } } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java index b539509688..e44f4cce13 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoAutoConfigurationTests.java @@ -24,6 +24,7 @@ import com.mongodb.client.MongoClients; import org.junit.jupiter.api.Test; import org.springframework.boot.autoconfigure.AutoConfigurations; +import org.springframework.boot.test.context.assertj.AssertableApplicationContext; import org.springframework.boot.test.context.runner.ApplicationContextRunner; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -36,6 +37,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Dave Syer * @author Stephane Nicoll + * @author Scott Frederick */ class MongoAutoConfigurationTests { @@ -50,24 +52,23 @@ class MongoAutoConfigurationTests { @Test void settingsAdded() { this.contextRunner.withUserConfiguration(SettingsConfig.class) - .run((context) -> assertThat(extractClientSettings(context.getBean(MongoClient.class)) - .getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300)); + .run((context) -> assertThat( + getSettings(context).getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)) + .isEqualTo(300)); } @Test void settingsAddedButNoHost() { this.contextRunner.withUserConfiguration(SettingsConfig.class) - .run((context) -> assertThat(extractClientSettings(context.getBean(MongoClient.class)) - .getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)).isEqualTo(300)); + .run((context) -> assertThat( + getSettings(context).getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)) + .isEqualTo(300)); } @Test void settingsSslConfig() { - this.contextRunner.withUserConfiguration(SslSettingsConfig.class).run((context) -> { - assertThat(context).hasSingleBean(MongoClient.class); - MongoClientSettings settings = extractClientSettings(context.getBean(MongoClient.class)); - assertThat(settings.getSslSettings().isEnabled()).isTrue(); - }); + this.contextRunner.withUserConfiguration(SslSettingsConfig.class) + .run((context) -> assertThat(getSettings(context).getSslSettings().isEnabled()).isTrue()); } @Test @@ -76,7 +77,16 @@ class MongoAutoConfigurationTests { .run((context) -> assertThat(context).hasSingleBean(MongoClient.class)); } - private static MongoClientSettings extractClientSettings(MongoClient client) { + @Test + void customizerOverridesAutoConfig() { + this.contextRunner.withPropertyValues("spring.data.mongodb.uri:mongodb://localhost/test?appname=auto-config") + .withUserConfiguration(SimpleCustomizerConfig.class) + .run((context) -> assertThat(getSettings(context).getApplicationName()).isEqualTo("overridden-name")); + } + + private MongoClientSettings getSettings(AssertableApplicationContext context) { + assertThat(context).hasSingleBean(MongoClient.class); + MongoClient client = context.getBean(MongoClient.class); return (MongoClientSettings) ReflectionTestUtils.getField(client, "settings"); } @@ -111,4 +121,14 @@ class MongoAutoConfigurationTests { } + @Configuration(proxyBeanMethods = false) + static class SimpleCustomizerConfig { + + @Bean + MongoClientSettingsBuilderCustomizer customizer() { + return (clientSettingsBuilder) -> clientSettingsBuilder.applicationName("overridden-name"); + } + + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupportTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupportTests.java new file mode 100644 index 0000000000..510dfbbb46 --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactorySupportTests.java @@ -0,0 +1,306 @@ +/* + * Copyright 2012-2020 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.mongo; + +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import com.mongodb.MongoClientSettings; +import com.mongodb.MongoCredential; +import com.mongodb.ServerAddress; +import org.bson.UuidRepresentation; +import org.junit.jupiter.api.Test; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.util.TestPropertyValues; +import org.springframework.context.annotation.AnnotationConfigApplicationContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; +import org.springframework.mock.env.MockEnvironment; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; + +/** + * Tests for {@link MongoClientFactorySupport}. + * + * @author Phillip Webb + * @author Andy Wilkinson + * @author Stephane Nicoll + * @author Mark Paluch + * @author Artsiom Yudovin + * @author Scott Frederick + */ +abstract class MongoClientFactorySupportTests { + + private MongoProperties properties = new MongoProperties(); + + private MockEnvironment environment = new MockEnvironment(); + + @Test + void canBindCharArrayPassword() { + // gh-1572 + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of("spring.data.mongodb.password:word").applyTo(context); + context.register(Config.class); + context.refresh(); + MongoProperties properties = context.getBean(MongoProperties.class); + assertThat(properties.getPassword()).isEqualTo("word".toCharArray()); + } + + @Test + void allMongoClientSettingsCanBeSet() { + MongoClientSettings.Builder builder = MongoClientSettings.builder(); + builder.applyToSocketSettings((settings) -> { + settings.connectTimeout(1000, TimeUnit.MILLISECONDS); + settings.readTimeout(1000, TimeUnit.MILLISECONDS); + }).applyToServerSettings((settings) -> { + settings.heartbeatFrequency(10001, TimeUnit.MILLISECONDS); + settings.minHeartbeatFrequency(501, TimeUnit.MILLISECONDS); + }).applyToConnectionPoolSettings((settings) -> { + settings.maxWaitTime(120001, TimeUnit.MILLISECONDS); + settings.maxConnectionLifeTime(60000, TimeUnit.MILLISECONDS); + settings.maxConnectionIdleTime(60000, TimeUnit.MILLISECONDS); + }).applyToSslSettings((settings) -> settings.enabled(true)).applicationName("test"); + + MongoClientSettings settings = builder.build(); + T client = createMongoClient(settings); + MongoClientSettings wrapped = getClientSettings(client); + assertThat(wrapped.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)) + .isEqualTo(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)); + assertThat(wrapped.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS)) + .isEqualTo(settings.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS)); + assertThat(wrapped.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS)) + .isEqualTo(settings.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS)); + assertThat(wrapped.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS)) + .isEqualTo(settings.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS)); + assertThat(wrapped.getApplicationName()).isEqualTo(settings.getApplicationName()); + assertThat(wrapped.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS)) + .isEqualTo(settings.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS)); + assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS)) + .isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS)); + assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS)) + .isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS)); + assertThat(wrapped.getSslSettings().isEnabled()).isEqualTo(settings.getSslSettings().isEnabled()); + } + + @Test + void portCanBeCustomized() { + this.properties.setPort(12345); + T client = createMongoClient(); + List allAddresses = getAllAddresses(client); + assertThat(allAddresses).hasSize(1); + assertServerAddress(allAddresses.get(0), "localhost", 12345); + } + + @Test + void hostCanBeCustomized() { + this.properties.setHost("mongo.example.com"); + T client = createMongoClient(); + List allAddresses = getAllAddresses(client); + assertThat(allAddresses).hasSize(1); + assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017); + } + + @Test + void credentialsCanBeCustomized() { + this.properties.setUsername("user"); + this.properties.setPassword("secret".toCharArray()); + T client = createMongoClient(); + assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test"); + } + + @Test + void databaseCanBeCustomized() { + this.properties.setDatabase("foo"); + this.properties.setUsername("user"); + this.properties.setPassword("secret".toCharArray()); + T client = createMongoClient(); + assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo"); + } + + @Test + void uuidRepresentationDefaultToJavaLegacy() { + T client = createMongoClient(); + assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.JAVA_LEGACY); + } + + @Test + void uuidRepresentationCanBeCustomized() { + this.properties.setUuidRepresentation(UuidRepresentation.STANDARD); + T client = createMongoClient(); + assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD); + } + + @Test + void authenticationDatabaseCanBeCustomized() { + this.properties.setAuthenticationDatabase("foo"); + this.properties.setUsername("user"); + this.properties.setPassword("secret".toCharArray()); + T client = createMongoClient(); + assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo"); + } + + @Test + void uriCanBeCustomized() { + this.properties.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test"); + T client = createMongoClient(); + List allAddresses = getAllAddresses(client); + assertThat(allAddresses).hasSize(2); + assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); + assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456); + assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test"); + } + + @Test + void uriIsIgnoredInEmbeddedMode() { + this.properties.setUri("mongodb://mongo.example.com:1234/mydb"); + this.environment.setProperty("local.mongo.port", "4000"); + T client = createMongoClient(); + List allAddresses = getAllAddresses(client); + assertThat(allAddresses).hasSize(1); + assertServerAddress(allAddresses.get(0), "localhost", 4000); + } + + @Test + void retryWritesIsPropagatedFromUri() { + this.properties.setUri("mongodb://localhost/test?retryWrites=true"); + T client = createMongoClient(); + assertThat(getClientSettings(client).getRetryWrites()).isTrue(); + } + + @Test + void uriCannotBeSetWithCredentials() { + this.properties.setUri("mongodb://127.0.0.1:1234/mydb"); + this.properties.setUsername("user"); + this.properties.setPassword("secret".toCharArray()); + assertThatIllegalStateException().isThrownBy(this::createMongoClient).withMessageContaining( + "Invalid mongo configuration, either uri or host/port/credentials must be specified"); + } + + @Test + void uriCannotBeSetWithHostPort() { + this.properties.setUri("mongodb://127.0.0.1:1234/mydb"); + this.properties.setHost("localhost"); + this.properties.setPort(4567); + assertThatIllegalStateException().isThrownBy(this::createMongoClient).withMessageContaining( + "Invalid mongo configuration, either uri or host/port/credentials must be specified"); + } + + @Test + void customizerIsInvoked() { + MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class); + createMongoClient(customizer); + verify(customizer).customize(any(MongoClientSettings.Builder.class)); + } + + @Test + void customizerIsInvokedWhenHostIsSet() { + this.properties.setHost("localhost"); + MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class); + createMongoClient(customizer); + verify(customizer).customize(any(MongoClientSettings.Builder.class)); + } + + @Test + void customizerIsInvokedForEmbeddedMongo() { + this.environment.setProperty("local.mongo.port", "27017"); + MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class); + createMongoClient(customizer); + verify(customizer).customize(any(MongoClientSettings.Builder.class)); + } + + @Test + void onlyHostAndPortSetShouldUseThat() { + this.properties.setHost("localhost"); + this.properties.setPort(27017); + T client = createMongoClient(); + List allAddresses = getAllAddresses(client); + assertThat(allAddresses).hasSize(1); + assertServerAddress(allAddresses.get(0), "localhost", 27017); + } + + @Test + void onlyUriSetShouldUseThat() { + this.properties.setUri("mongodb://mongo1.example.com:12345"); + T client = createMongoClient(); + List allAddresses = getAllAddresses(client); + assertThat(allAddresses).hasSize(1); + assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); + } + + @Test + void noCustomAddressAndNoUriUsesDefaultUri() { + T client = createMongoClient(); + List allAddresses = getAllAddresses(client); + assertThat(allAddresses).hasSize(1); + assertServerAddress(allAddresses.get(0), "localhost", 27017); + } + + @Test + void canBindAutoIndexCreation() { + AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); + TestPropertyValues.of("spring.data.mongodb.autoIndexCreation:true").applyTo(context); + context.register(Config.class); + context.refresh(); + MongoProperties properties = context.getBean(MongoProperties.class); + assertThat(properties.isAutoIndexCreation()).isTrue(); + } + + protected T createMongoClient() { + return createMongoClient(this.properties, this.environment, null, null); + } + + protected T createMongoClient(MongoClientSettings settings) { + return createMongoClient(this.properties, this.environment, null, settings); + } + + protected void createMongoClient(MongoClientSettingsBuilderCustomizer... customizers) { + createMongoClient(this.properties, this.environment, (customizers != null) ? Arrays.asList(customizers) : null, + null); + } + + protected abstract T createMongoClient(MongoProperties properties, Environment environment, + List customizers, MongoClientSettings settings); + + protected abstract MongoClientSettings getClientSettings(T client); + + protected abstract List getAllAddresses(T client); + + protected void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) { + assertThat(serverAddress.getHost()).isEqualTo(expectedHost); + assertThat(serverAddress.getPort()).isEqualTo(expectedPort); + } + + protected void assertMongoCredential(MongoCredential credentials, String expectedUsername, String expectedPassword, + String expectedSource) { + assertThat(credentials.getUserName()).isEqualTo(expectedUsername); + assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray()); + assertThat(credentials.getSource()).isEqualTo(expectedSource); + } + + @Configuration(proxyBeanMethods = false) + @EnableConfigurationProperties(MongoProperties.class) + static class Config { + + } + +} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java index 7086057deb..2f2c99e4e6 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoClientFactoryTests.java @@ -19,18 +19,12 @@ package org.springframework.boot.autoconfigure.mongo; import java.util.List; import com.mongodb.MongoClientSettings; -import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; import com.mongodb.client.MongoClient; -import org.bson.UuidRepresentation; -import org.junit.jupiter.api.Test; import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; import org.springframework.test.util.ReflectionTestUtils; -import static org.assertj.core.api.Assertions.assertThat; - /** * Tests for {@link MongoClientFactory}. * @@ -38,124 +32,24 @@ import static org.assertj.core.api.Assertions.assertThat; * @author Andy Wilkinson * @author Stephane Nicoll * @author Mark Paluch + * @author Scott Frederick */ -class MongoClientFactoryTests { - - private MockEnvironment environment = new MockEnvironment(); - - @Test - void portCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setPort(12345); - MongoClient client = createMongoClient(properties); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "localhost", 12345); - } - - @Test - void hostCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setHost("mongo.example.com"); - MongoClient client = createMongoClient(properties); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017); - } - - @Test - void credentialsCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setUsername("user"); - properties.setPassword("secret".toCharArray()); - MongoClient client = createMongoClient(properties); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test"); - } - - @Test - void databaseCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setDatabase("foo"); - properties.setUsername("user"); - properties.setPassword("secret".toCharArray()); - MongoClient client = createMongoClient(properties); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo"); - } - - @Test - void uuidRepresentationDefaultToJavaLegacy() { - MongoProperties properties = new MongoProperties(); - MongoClient client = createMongoClient(properties); - assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.JAVA_LEGACY); - } - - @Test - void uuidRepresentationCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setUuidRepresentation(UuidRepresentation.STANDARD); - MongoClient client = createMongoClient(properties); - assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD); - } - - @Test - void authenticationDatabaseCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setAuthenticationDatabase("foo"); - properties.setUsername("user"); - properties.setPassword("secret".toCharArray()); - MongoClient client = createMongoClient(properties); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo"); - } - - @Test - void uriCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test"); - MongoClient client = createMongoClient(properties); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(2); - assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); - assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test"); - } - - @Test - void uriIsIgnoredInEmbeddedMode() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://mongo.example.com:1234/mydb"); - this.environment.setProperty("local.mongo.port", "4000"); - MongoClient client = createMongoClient(properties, this.environment); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "localhost", 4000); - } +class MongoClientFactoryTests extends MongoClientFactorySupportTests { - private MongoClient createMongoClient(MongoProperties properties) { - return createMongoClient(properties, null); + @Override + protected MongoClient createMongoClient(MongoProperties properties, Environment environment, + List customizers, MongoClientSettings settings) { + return new MongoClientFactory(properties, environment, customizers).createMongoClient(settings); } - private MongoClient createMongoClient(MongoProperties properties, Environment environment) { - return new MongoClientFactory(properties, environment).createMongoClient(null); - } - - private List getAllAddresses(MongoClient client) { + @Override + protected List getAllAddresses(MongoClient client) { return client.getClusterDescription().getClusterSettings().getHosts(); } - private MongoClientSettings getClientSettings(MongoClient client) { + @Override + protected MongoClientSettings getClientSettings(MongoClient client) { return (MongoClientSettings) ReflectionTestUtils.getField(client, "settings"); } - private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) { - assertThat(serverAddress.getHost()).isEqualTo(expectedHost); - assertThat(serverAddress.getPort()).isEqualTo(expectedPort); - } - - private void assertMongoCredential(MongoCredential credentials, String expectedUsername, String expectedPassword, - String expectedSource) { - assertThat(credentials.getUserName()).isEqualTo(expectedUsername); - assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray()); - assertThat(credentials.getSource()).isEqualTo(expectedSource); - } - } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java deleted file mode 100644 index 52a150ac4a..0000000000 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/MongoPropertiesTests.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright 2012-2020 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.mongo; - -import java.util.List; -import java.util.concurrent.TimeUnit; - -import com.mongodb.MongoClientSettings; -import com.mongodb.ServerAddress; -import com.mongodb.client.MongoClient; -import org.junit.jupiter.api.Test; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.boot.test.util.TestPropertyValues; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Configuration; -import org.springframework.test.util.ReflectionTestUtils; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * Tests for {@link MongoProperties}. - * - * @author Phillip Webb - * @author Andy Wilkinson - * @author Stephane Nicoll - * @author Mark Paluch - * @author Artsiom Yudovin - */ -class MongoPropertiesTests { - - @Test - void canBindCharArrayPassword() { - // gh-1572 - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.data.mongodb.password:word").applyTo(context); - context.register(Config.class); - context.refresh(); - MongoProperties properties = context.getBean(MongoProperties.class); - assertThat(properties.getPassword()).isEqualTo("word".toCharArray()); - } - - @Test - void allMongoClientSettingsCanBeSet() { - MongoClientSettings.Builder builder = MongoClientSettings.builder(); - builder.applyToSocketSettings((settings) -> { - settings.connectTimeout(1000, TimeUnit.MILLISECONDS); - settings.readTimeout(1000, TimeUnit.MILLISECONDS); - }).applyToServerSettings((settings) -> { - settings.heartbeatFrequency(10001, TimeUnit.MILLISECONDS); - settings.minHeartbeatFrequency(501, TimeUnit.MILLISECONDS); - }).applyToConnectionPoolSettings((settings) -> { - settings.maxWaitTime(120001, TimeUnit.MILLISECONDS); - settings.maxConnectionLifeTime(60000, TimeUnit.MILLISECONDS); - settings.maxConnectionIdleTime(60000, TimeUnit.MILLISECONDS); - }).applyToSslSettings((settings) -> settings.enabled(true)).applicationName("test"); - - MongoClientSettings settings = builder.build(); - MongoProperties properties = new MongoProperties(); - MongoClient client = createMongoClient(properties, settings); - MongoClientSettings wrapped = (MongoClientSettings) ReflectionTestUtils.getField(client, "settings"); - assertThat(wrapped.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)) - .isEqualTo(settings.getSocketSettings().getConnectTimeout(TimeUnit.MILLISECONDS)); - assertThat(wrapped.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS)) - .isEqualTo(settings.getSocketSettings().getReadTimeout(TimeUnit.MILLISECONDS)); - assertThat(wrapped.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS)) - .isEqualTo(settings.getServerSettings().getHeartbeatFrequency(TimeUnit.MILLISECONDS)); - assertThat(wrapped.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS)) - .isEqualTo(settings.getServerSettings().getMinHeartbeatFrequency(TimeUnit.MILLISECONDS)); - assertThat(wrapped.getApplicationName()).isEqualTo(settings.getApplicationName()); - assertThat(wrapped.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS)) - .isEqualTo(settings.getConnectionPoolSettings().getMaxWaitTime(TimeUnit.MILLISECONDS)); - assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS)) - .isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionLifeTime(TimeUnit.MILLISECONDS)); - assertThat(wrapped.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS)) - .isEqualTo(settings.getConnectionPoolSettings().getMaxConnectionIdleTime(TimeUnit.MILLISECONDS)); - assertThat(wrapped.getSslSettings().isEnabled()).isEqualTo(settings.getSslSettings().isEnabled()); - } - - @Test - void uriOverridesHostAndPort() { - MongoProperties properties = new MongoProperties(); - properties.setHost("localhost"); - properties.setPort(27017); - properties.setUri("mongodb://mongo1.example.com:12345"); - MongoClient client = createMongoClient(properties); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); - } - - @Test - void onlyHostAndPortSetShouldUseThat() { - MongoProperties properties = new MongoProperties(); - properties.setHost("localhost"); - properties.setPort(27017); - MongoClient client = createMongoClient(properties); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "localhost", 27017); - } - - @Test - void onlyUriSetShouldUseThat() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://mongo1.example.com:12345"); - MongoClient client = createMongoClient(properties); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); - } - - @Test - void noCustomAddressAndNoUriUsesDefaultUri() { - MongoProperties properties = new MongoProperties(); - MongoClient client = createMongoClient(properties); - List allAddresses = getAllAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "localhost", 27017); - } - - private MongoClient createMongoClient(MongoProperties properties, MongoClientSettings settings) { - return new MongoClientFactory(properties, null).createMongoClient(settings); - } - - private MongoClient createMongoClient(MongoProperties properties) { - return createMongoClient(properties, null); - } - - private List getAllAddresses(MongoClient client) { - return client.getClusterDescription().getClusterSettings().getHosts(); - } - - @Test - void canBindAutoIndexCreation() { - AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(); - TestPropertyValues.of("spring.data.mongodb.autoIndexCreation:true").applyTo(context); - context.register(Config.class); - context.refresh(); - MongoProperties properties = context.getBean(MongoProperties.class); - assertThat(properties.isAutoIndexCreation()).isTrue(); - } - - private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) { - assertThat(serverAddress.getHost()).isEqualTo(expectedHost); - assertThat(serverAddress.getPort()).isEqualTo(expectedPort); - } - - @Configuration(proxyBeanMethods = false) - @EnableConfigurationProperties(MongoProperties.class) - static class Config { - - } - -} diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java index 129c5456e0..cdf9806531 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/mongo/ReactiveMongoClientFactoryTests.java @@ -16,210 +16,43 @@ package org.springframework.boot.autoconfigure.mongo; -import java.util.Arrays; import java.util.List; import com.mongodb.MongoClientSettings; -import com.mongodb.MongoCredential; import com.mongodb.ServerAddress; import com.mongodb.connection.ClusterSettings; import com.mongodb.internal.async.client.AsyncMongoClient; import com.mongodb.reactivestreams.client.MongoClient; -import org.bson.UuidRepresentation; -import org.junit.jupiter.api.Test; import org.springframework.core.env.Environment; -import org.springframework.mock.env.MockEnvironment; import org.springframework.test.util.ReflectionTestUtils; -import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; - /** * Tests for {@link ReactiveMongoClientFactory}. * * @author Mark Paluch * @author Stephane Nicoll + * @author Scott Frederick */ -class ReactiveMongoClientFactoryTests { - - private MockEnvironment environment = new MockEnvironment(); - - @Test - void portCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setPort(12345); - MongoClient client = createMongoClient(properties); - List allAddresses = extractServerAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "localhost", 12345); - } - - @Test - void hostCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setHost("mongo.example.com"); - MongoClient client = createMongoClient(properties); - List allAddresses = extractServerAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "mongo.example.com", 27017); - } - - @Test - void credentialsCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setUsername("user"); - properties.setPassword("secret".toCharArray()); - MongoClient client = createMongoClient(properties); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test"); - } - - @Test - void databaseCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setDatabase("foo"); - properties.setUsername("user"); - properties.setPassword("secret".toCharArray()); - MongoClient client = createMongoClient(properties); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo"); - } - - @Test - void uuidRepresentationDefaultToJavaLegacy() { - MongoProperties properties = new MongoProperties(); - MongoClient client = createMongoClient(properties); - assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.JAVA_LEGACY); - } - - @Test - void uuidRepresentationCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setUuidRepresentation(UuidRepresentation.STANDARD); - MongoClient client = createMongoClient(properties); - assertThat(getClientSettings(client).getUuidRepresentation()).isEqualTo(UuidRepresentation.STANDARD); - } - - @Test - void authenticationDatabaseCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setAuthenticationDatabase("foo"); - properties.setUsername("user"); - properties.setPassword("secret".toCharArray()); - MongoClient client = createMongoClient(properties); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "foo"); - } - - @Test - void uriCanBeCustomized() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://user:secret@mongo1.example.com:12345,mongo2.example.com:23456/test"); - MongoClient client = createMongoClient(properties); - List allAddresses = extractServerAddresses(client); - assertThat(allAddresses).hasSize(2); - assertServerAddress(allAddresses.get(0), "mongo1.example.com", 12345); - assertServerAddress(allAddresses.get(1), "mongo2.example.com", 23456); - assertMongoCredential(getClientSettings(client).getCredential(), "user", "secret", "test"); - } - - @Test - void retryWritesIsPropagatedFromUri() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://localhost/test?retryWrites=true"); - MongoClient client = createMongoClient(properties); - assertThat(getClientSettings(client).getRetryWrites()).isTrue(); - } - - @Test - void uriCannotBeSetWithCredentials() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://127.0.0.1:1234/mydb"); - properties.setUsername("user"); - properties.setPassword("secret".toCharArray()); - assertThatIllegalStateException().isThrownBy(() -> createMongoClient(properties)).withMessageContaining( - "Invalid mongo configuration, either uri or host/port/credentials must be specified"); - } - - @Test - void uriCannotBeSetWithHostPort() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://127.0.0.1:1234/mydb"); - properties.setHost("localhost"); - properties.setPort(4567); - assertThatIllegalStateException().isThrownBy(() -> createMongoClient(properties)).withMessageContaining( - "Invalid mongo configuration, either uri or host/port/credentials must be specified"); - } +class ReactiveMongoClientFactoryTests extends MongoClientFactorySupportTests { - @Test - void uriIsIgnoredInEmbeddedMode() { - MongoProperties properties = new MongoProperties(); - properties.setUri("mongodb://mongo.example.com:1234/mydb"); - this.environment.setProperty("local.mongo.port", "4000"); - MongoClient client = createMongoClient(properties, this.environment); - List allAddresses = extractServerAddresses(client); - assertThat(allAddresses).hasSize(1); - assertServerAddress(allAddresses.get(0), "localhost", 4000); + @Override + protected MongoClient createMongoClient(MongoProperties properties, Environment environment, + List customizers, MongoClientSettings settings) { + return new ReactiveMongoClientFactory(properties, environment, customizers).createMongoClient(settings); } - @Test - void customizerIsInvoked() { - MongoProperties properties = new MongoProperties(); - MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class); - createMongoClient(properties, this.environment, customizer); - verify(customizer).customize(any(MongoClientSettings.Builder.class)); - } - - @Test - void customizerIsInvokedWhenHostIsSet() { - MongoProperties properties = new MongoProperties(); - properties.setHost("localhost"); - MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class); - createMongoClient(properties, this.environment, customizer); - verify(customizer).customize(any(MongoClientSettings.Builder.class)); - } - - @Test - void customizerIsInvokedForEmbeddedMongo() { - MongoProperties properties = new MongoProperties(); - this.environment.setProperty("local.mongo.port", "27017"); - MongoClientSettingsBuilderCustomizer customizer = mock(MongoClientSettingsBuilderCustomizer.class); - createMongoClient(properties, this.environment, customizer); - verify(customizer).customize(any(MongoClientSettings.Builder.class)); - } - - private MongoClient createMongoClient(MongoProperties properties) { - return createMongoClient(properties, this.environment); - } - - private MongoClient createMongoClient(MongoProperties properties, Environment environment, - MongoClientSettingsBuilderCustomizer... customizers) { - return new ReactiveMongoClientFactory(properties, environment, Arrays.asList(customizers)) - .createMongoClient(null); - } - - private List extractServerAddresses(MongoClient client) { + @Override + protected List getAllAddresses(MongoClient client) { MongoClientSettings settings = getClientSettings(client); ClusterSettings clusterSettings = settings.getClusterSettings(); return clusterSettings.getHosts(); } - private MongoClientSettings getClientSettings(MongoClient client) { + @Override + protected MongoClientSettings getClientSettings(MongoClient client) { AsyncMongoClient wrapped = (AsyncMongoClient) ReflectionTestUtils.getField(client, "wrapped"); return (MongoClientSettings) ReflectionTestUtils.getField(wrapped, "settings"); } - private void assertServerAddress(ServerAddress serverAddress, String expectedHost, int expectedPort) { - assertThat(serverAddress.getHost()).isEqualTo(expectedHost); - assertThat(serverAddress.getPort()).isEqualTo(expectedPort); - } - - private void assertMongoCredential(MongoCredential credentials, String expectedUsername, String expectedPassword, - String expectedSource) { - assertThat(credentials.getUserName()).isEqualTo(expectedUsername); - assertThat(credentials.getPassword()).isEqualTo(expectedPassword.toCharArray()); - assertThat(credentials.getSource()).isEqualTo(expectedSource); - } - }