Fehler beim Versuch, MongoDB über Testcontainer zu testen (Dieser Host ist unbekannt)Java

Java-Forum
Guest
 Fehler beim Versuch, MongoDB über Testcontainer zu testen (Dieser Host ist unbekannt)

Post by Guest »

Ich habe einen Dienst unter Spring Boot, bei dem eine benutzerdefinierte Konfiguration eingerichtet wird, die mit dem ReplicaSet von MongoDB funktioniert

Code: Select all

plugins {
id 'java'
id 'org.springframework.boot' version '3.2.1'
id 'io.spring.dependency-management' version '1.1.4'
}

java {
toolchain {
languageVersion = JavaLanguageVersion.of(17)
}
}

....

Code: Select all

@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(MongoPropertiesCustom.class)
@EnableReactiveMongoRepositories(basePackageClasses = {SubscriptionRepository.class})
public class MongoConfig extends AbstractReactiveMongoConfiguration {

private final MongoPropertiesCustom mongoPropertiesCustom;

@Override
protected String getDatabaseName() {
return mongoPropertiesCustom.getDatabase();
}

@Override
public MongoClient reactiveMongoClient() {
return MongoClients.create(mongoPropertiesCustom.buildUri());
}

@Bean
public ReactiveMongoTemplate reactiveMongoTemplate() {
return new ReactiveMongoTemplate(reactiveMongoClient(), getDatabaseName());
}
@Bean
public CommandLineRunner initializeIndexes(ReactiveMongoTemplate mongoTemplate) {
return args -> {

mongoTemplate.indexOps(SubscriptionDocument.class)
.ensureIndex(new Index().on("id", Sort.Direction.ASC).unique())
.subscribe();
mongoTemplate.indexOps(ProcessingError.class)
.ensureIndex(new Index().on("timestamp", Sort.Direction.DESC))
.subscribe();
};
}

@Bean
public ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory factory) {
return new ReactiveMongoTransactionManager(factory);
}
}

Code: Select all

@ConfigurationProperties(prefix = "mongodb")
@Data
public class MongoPropertiesCustom {

private String host = "";
private int port = 0;
private String database = "";
private String username;
private String password;
private String authSource = "";
private String replicaSet;

public String buildUri() {
return String.format("mongodb://%s:%s@%s:%d/%s?authSource=%s&replicaSet=%s",
username, password, host, port, database, authSource, replicaSet);
}
}

Code: Select all

@Component
@RequiredArgsConstructor
@Slf4j
public class SubscriptionRepository {

private final ReactiveMongoTemplate mongoTemplate;
private final ReactiveMongoTransactionManager transactionManager;

public Mono save(SubscriptionDocument subscription) {

TransactionalOperator transactionalOperator = TransactionalOperator.create(transactionManager);

return mongoTemplate.save(subscription)
.doOnSuccess(saved -> log.debug("Saved subscription: {}", saved))
.doOnError(error ->  log.error("Error saving subscription: {}", error.getMessage()))

.as(transactionalOperator::transactional);
}
............
Tests

Code: Select all

@SpringBootTest(classes = {
MongoConfig.class,
SubscriptionRepository.class
})
@ActiveProfiles("test")
@Testcontainers
class SubscriptionRepositoryTest {
private static final Logger log = LoggerFactory.getLogger(SubscriptionRepositoryTest.class);

@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:6.0")
.withCommand(
"--replSet", "rs0",
"--bind_ip_all",
"--setParameter", "transactionLifetimeLimitSeconds=30"
);

@Autowired
private SubscriptionRepository subscriptionRepository;

@DynamicPropertySource
static void setProperties(DynamicPropertyRegistry registry) {
mongoDBContainer.start();

String containerIpAddress = mongoDBContainer.getHost();
Integer mappedPort = mongoDBContainer.getFirstMappedPort();

log.info("MongoDB container started at {}:{}", containerIpAddress, mappedPort);

initializeReplicaSet(mongoDBContainer);

registry.add("mongodb.host", () -> containerIpAddress);
registry.add("mongodb.port", () -> mappedPort);
registry.add("mongodb.database", () -> "test");
registry.add("mongodb.username", () -> "root");
registry.add("mongodb.password", () -> "root");
registry.add("mongodb.authSource", () -> "admin");
registry.add("mongodb.replicaSet", () -> "rs0");
}

private static void initializeReplicaSet(MongoDBContainer container) {
try {

log.info("Starting replica set initialization...");
Thread.sleep(1000);

String containerIpAddress = container.getHost();
Integer mappedPort = container.getFirstMappedPort();

log.info("Using host: {}, port: {}", containerIpAddress, mappedPort);

String rsConfig = String.format(
"rs.initiate({" +
"_id: 'rs0'," +
"members: [{" +
"_id: 0," +
"host: '%s:%d'," +
"priority: 1" +
"}]," +
"settings: {" +
"electionTimeoutMillis: 2000" +

"}"  +
"})",
containerIpAddress, mappedPort
);

log.info("Initializing replica set with config: {}", rsConfig);

org.testcontainers.containers.Container.ExecResult initResult = container.execInContainer(
"mongosh",
"--eval",
rsConfig
);
log.info("Initialization result - stdout: {}", initResult.getStdout());

org.testcontainers.containers.Container.ExecResult statusResult = container.execInContainer(
"mongosh",
"--eval",
"rs.status()"
);
log.info("Replica set status: {}", statusResult.getStdout());
Thread.sleep(2000);

ConnectionString connectionString = new ConnectionString(
String.format("mongodb://%s:%d/?directConnection=true",
containerIpAddress, mappedPort)
);

try (MongoClient testClient = MongoClients.create(connectionString)) {
Mono.from(testClient.getDatabase("admin")
.runCommand(new Document("ping", 1)))
.block(Duration.ofSeconds(10));
log.info("Replica set initialized successfully");

String createUserCommand = "db.getSiblingDB('admin').createUser({" +
"user: 'root'," +
"pwd: 'root'," +
"roles: ['root']" +
"})";

org.testcontainers.containers.Container.ExecResult createUserResult = container.execInContainer(
"mongosh",
"--eval",
createUserCommand
);
log.info("Create user result: {}", createUserResult.getStdout());

String checkUserCommand = "db.getSiblingDB('admin').getUser('root')";
org.testcontainers.containers.Container.ExecResult checkUserResult = container.execInContainer(
"mongosh",
"--eval",
checkUserCommand
);
log.info("User check result: {}", checkUserResult.getStdout());

String authTestCommand = "db.getSiblingDB('admin').auth('root', 'root')";
org.testcontainers.containers.Container.ExecResult authTestResult = container.execInContainer(
"mongosh",
"--eval",
authTestCommand
);
log.info("Auth test result: {}", authTestResult.getStdout());
}

} catch (Exception e) {
log.error("Failed to initialize replica set", e);
throw new RuntimeException("Failed to initialize replica set", e);
}
}

@BeforeEach
void setUp() {
log.info("Cleaning up database before test");
subscriptionRepository.dropAllCollections()
.doOnSuccess(v -> log.info("Database cleaned successfully"))
.doOnError(e -> log.error("Error cleaning database", e))
.block();
}

.....

Nach wann werden Tests ausgeführt ....

2025-01-18T20:43:08.861+03: 00 INFO 2560 --- [consumer] [-localhost:3316] org.mongodb.driver.cluster: Server localhost:3316 ist kein Mitglied des Replikatsatzes mehr. Wird aus der Clientansicht des Clusters entfernt.
2025-01-18T20:43:08.862+03:00 INFO 2560 --- [consumer] [-localhost:3316] org.mongodb.driver.cluster: Erkannter primärer Replikatsatz localhost:3316 mit maximaler Wahl-ID 7fffffff0000000000000001 und maximal festgelegte Version 1
2025-01-18T20:43:09.233+03:00 INFO 2560 --- [Verbraucher] [Testarbeiter] c.repository.SubscriptionRepositoryTest: SubscriptionRepositoryTest in 8,815 Sekunden gestartet (Prozess läuft seit 14.105)
2025-01-18T20:43:09.317+03:00 INFO 2560 --- [Verbraucher] [Testarbeiter] org.mongodb.driver.cluster: Kein Server von WritableServerSelector aus der Clusterbeschreibung ClusterDescription{Typ ausgewählt =REPLICA_SET, ConnectionMode=MULTIPLE, serverDescriptions=[ServerDescription{address=localhost:3316, type=UNKNOWN, state=CONNECTING}]}. 30.000 ms warten, bevor das Zeitlimit überschritten wird
2025-01-18T20:43:09.324+03:00 INFO 2560 --- [Verbraucher] [Testarbeiter] org.mongodb.driver.cluster: Kein Server von WritableServerSelector ausgewählt Clusterbeschreibung ClusterDescription{type=REPLICA_SET, ConnectionMode=MULTIPLE, serverDescriptions=[ServerDescription{address=localhost:3316, type=UNKNOWN, state=CONNECTING}]}. 30.000 ms warten, bevor das Zeitlimit überschritten wird
2025-01-18T20:43:10.541+03:00 INFO 2560 --- [consumer] [ Test worker] c.repository.SubscriptionRepositoryTest: Bereinigen der Datenbank vor dem Test
2025-01-18T20:43:10.638+03:00 INFO 2560 --- [Verbraucher] [Testarbeiter] org.mongodb.driver.cluster: Kein Server von ReadPreferenceServerSelector{readPreference=primary} aus der Clusterbeschreibung ClusterDescription{type=REPLICA_SET, ConnectionMode=MULTIPLE, serverDescriptions=[ServerDescription{address=localhost :3316, Typ=UNBEKANNT, Status=VERBINDUNG}]}. 30.000 ms warten, bevor das Zeitlimit überschritten wird
2025-01-18T20:43:11.151+03:00 INFO 2560 --- [consumer] [3de90b922:27017] org.mongodb.driver.cluster: Ausnahme im Überwachungsthread while Verbindung zum Server herstellen 3c43de90b922:27017

com.mongodb.MongoSocketException: Dieser Host ist unbekannt (3c43de90b922)
at com.mongodb.ServerAddress.getSocketAddresses(ServerAddress. java:221) ~[mongodb-driver-core-4.11.1.jar:na]
Hat jemand eine Idee, warum die Initialisierung des Replikatsatzes erfolgreich ist, ebenso wie die Prüfungen und dann der ConnectionString für ReactiveMongoTemplate wurde ebenfalls erfolgreich erstellt, aber zu einem bestimmten Zeitpunkt wurde nicht auf die externe Adresse zugegriffen, d. h. MongoDB im Container verwendet seinen internen Hostnamen (22e0b261103c), dieser Hostname jedoch nicht außerhalb des Containers verfügbar?

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post