Add @ServiceContext support for MongoDB Atlas

Signed-off-by: Wouter Blancquaert <wouter@blancquaert.org>
This commit is contained in:
Wouter Blancquaert 2025-04-28 09:56:49 +02:00 committed by Wouter Blancquaert
parent c6045c3111
commit 37f64feedc
5 changed files with 161 additions and 32 deletions

View File

@ -0,0 +1,79 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testcontainers.service.connection.mongo;
import java.util.function.Function;
import com.mongodb.ConnectionString;
import org.testcontainers.containers.GenericContainer;
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
/**
* Abstract {@link ContainerConnectionDetailsFactory} to create {@link MongoConnectionDetails} from
* a {@link ServiceConnection @ServiceConnection}-annotated {@link T}.
*
* @author Moritz Halbritter
* @author Andy Wilkinson
* @author Phillip Webb
* @author Wouter Blancquaert
*/
abstract class AbstractMongoContainerConnectionDetailsFactory<T extends GenericContainer<T>>
extends ContainerConnectionDetailsFactory<T, MongoConnectionDetails> {
private final Function<T, String> connectionStringFunction;
AbstractMongoContainerConnectionDetailsFactory(Function<T, String> connectionStringFunction) {
super(ANY_CONNECTION_NAME, "com.mongodb.ConnectionString");
this.connectionStringFunction = connectionStringFunction;
}
@Override
protected MongoConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<T> source) {
return new MongoContainerConnectionDetails<>(source, this.connectionStringFunction);
}
/**
* {@link MongoConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class MongoContainerConnectionDetails<T extends GenericContainer<T>> extends ContainerConnectionDetails<T>
implements MongoConnectionDetails {
private final Function<T, String> connectionStringFunction;
private MongoContainerConnectionDetails(ContainerConnectionSource<T> source, Function<T, String> connectionStringFunction) {
super(source);
this.connectionStringFunction = connectionStringFunction;
}
@Override
public ConnectionString getConnectionString() {
return new ConnectionString(this.connectionStringFunction.apply(getContainer()));
}
@Override
public SslBundle getSslBundle() {
return super.getSslBundle();
}
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testcontainers.service.connection.mongo;
import org.testcontainers.mongodb.MongoDBAtlasLocalContainer;
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
/**
* {@link ContainerConnectionDetailsFactory} to create {@link MongoConnectionDetails} from
* a {@link ServiceConnection @ServiceConnection}-annotated {@link MongoDBAtlasLocalContainer}.
*
* @author Wouter Blancquaert
*/
class MongoAtlasContainerConnectionDetailsFactory
extends AbstractMongoContainerConnectionDetailsFactory<MongoDBAtlasLocalContainer> {
MongoAtlasContainerConnectionDetailsFactory() {
super(MongoDBAtlasLocalContainer::getDatabaseConnectionString);
}
}

View File

@ -16,13 +16,10 @@
package org.springframework.boot.testcontainers.service.connection.mongo;
import com.mongodb.ConnectionString;
import org.testcontainers.containers.MongoDBContainer;
import org.springframework.boot.autoconfigure.mongo.MongoConnectionDetails;
import org.springframework.boot.ssl.SslBundle;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactory;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionSource;
import org.springframework.boot.testcontainers.service.connection.ServiceConnection;
/**
@ -34,37 +31,10 @@ import org.springframework.boot.testcontainers.service.connection.ServiceConnect
* @author Phillip Webb
*/
class MongoContainerConnectionDetailsFactory
extends ContainerConnectionDetailsFactory<MongoDBContainer, MongoConnectionDetails> {
extends AbstractMongoContainerConnectionDetailsFactory<MongoDBContainer> {
MongoContainerConnectionDetailsFactory() {
super(ANY_CONNECTION_NAME, "com.mongodb.ConnectionString");
}
@Override
protected MongoConnectionDetails getContainerConnectionDetails(ContainerConnectionSource<MongoDBContainer> source) {
return new MongoContainerConnectionDetails(source);
}
/**
* {@link MongoConnectionDetails} backed by a {@link ContainerConnectionSource}.
*/
private static final class MongoContainerConnectionDetails extends ContainerConnectionDetails<MongoDBContainer>
implements MongoConnectionDetails {
private MongoContainerConnectionDetails(ContainerConnectionSource<MongoDBContainer> source) {
super(source);
}
@Override
public ConnectionString getConnectionString() {
return new ConnectionString(getContainer().getReplicaSetUrl());
}
@Override
public SslBundle getSslBundle() {
return super.getSslBundle();
}
super(MongoDBContainer::getReplicaSetUrl);
}
}

View File

@ -26,6 +26,7 @@ org.springframework.boot.testcontainers.service.connection.ldap.LLdapContainerCo
org.springframework.boot.testcontainers.service.connection.ldap.OpenLdapContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.liquibase.LiquibaseContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.mongo.MongoContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.mongo.MongoAtlasContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.neo4j.Neo4jContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.otlp.GrafanaOpenTelemetryLoggingContainerConnectionDetailsFactory,\
org.springframework.boot.testcontainers.service.connection.otlp.GrafanaOpenTelemetryMetricsContainerConnectionDetailsFactory,\

View File

@ -0,0 +1,41 @@
/*
* Copyright 2012-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.testcontainers.service.connection.mongo;
import com.mongodb.ConnectionString;
import org.junit.jupiter.api.Test;
import org.springframework.aot.hint.RuntimeHints;
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
import org.springframework.boot.testcontainers.service.connection.ContainerConnectionDetailsFactoryHints;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Tests for {@link MongoAtlasContainerConnectionDetailsFactoryTests}.
*
* @author Wouter Blancquaert
*/
class MongoAtlasContainerConnectionDetailsFactoryTests {
@Test
void shouldRegisterHints() {
RuntimeHints hints = ContainerConnectionDetailsFactoryHints.getRegisteredHints(getClass().getClassLoader());
assertThat(RuntimeHintsPredicates.reflection().onType(ConnectionString.class)).accepts(hints);
}
}