diff --git a/pom.xml b/pom.xml
index 55770299..d42f8c84 100644
--- a/pom.xml
+++ b/pom.xml
@@ -35,10 +35,10 @@
3.12.0
3.2.2
3.3.10
- 4.4.2
+ 4.8.2
3.5.4
- 4.9.0
3.12.4
+ 2.17.2
diff --git a/sharding-driver/pom.xml b/sharding-driver/pom.xml
index e39ef1c6..e3d6ecf8 100644
--- a/sharding-driver/pom.xml
+++ b/sharding-driver/pom.xml
@@ -25,12 +25,12 @@
org.mongodb
mongodb-driver-sync
- ${mongodb.driver.executable.version}
+ ${mongodb.driver.version}
org.mongodb
mongodb-driver-reactivestreams
- ${mongodb.driver.reactive.version}
+ ${mongodb.driver.version}
io.projectreactor
diff --git a/sharding-spring/pom.xml b/sharding-spring/pom.xml
index 6e915011..5c786c4b 100644
--- a/sharding-spring/pom.xml
+++ b/sharding-spring/pom.xml
@@ -28,11 +28,6 @@
spring-data-mongodb
${spring.data.mongodb.version}
-
- org.mongodb
- mongodb-driver-reactivestreams
- ${mongodb.driver.reactive.version}
-
io.projectreactor
reactor-core
@@ -41,8 +36,44 @@
org.mongodb
mongodb-driver-sync
- ${mongodb.driver.executable.version}
+ ${mongodb.driver.version}
+
+
+ org.mongodb
+ mongodb-driver-reactivestreams
+ ${mongodb.driver.version}
+
+
+
+ org.mongodb
+ mongodb-driver-core
+ ${mongodb.driver.version}
+
+ org.mongodb
+ bson
+ ${mongodb.driver.version}
+
+
+
+ org.apache.logging.log4j
+ log4j-api
+ ${log4j2.version}
+ test
+
+
+ org.apache.logging.log4j
+ log4j-core
+ ${log4j2.version}
+ test
+
+
+ org.apache.logging.log4j
+ log4j-slf4j-impl
+ ${log4j2.version}
+ test
+
+
diff --git a/sharding-spring/src/main/java/com/alpha/mongodb/sharding/core/template/CollectionShardedReactiveMongoTemplate.java b/sharding-spring/src/main/java/com/alpha/mongodb/sharding/core/template/CollectionShardedReactiveMongoTemplate.java
index 8a2ff905..dad314fa 100644
--- a/sharding-spring/src/main/java/com/alpha/mongodb/sharding/core/template/CollectionShardedReactiveMongoTemplate.java
+++ b/sharding-spring/src/main/java/com/alpha/mongodb/sharding/core/template/CollectionShardedReactiveMongoTemplate.java
@@ -11,13 +11,19 @@
import com.mongodb.reactivestreams.client.MongoCollection;
import org.apache.commons.collections.CollectionUtils;
import org.bson.Document;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
import org.springframework.data.mongodb.core.FindPublisherPreparer;
import org.springframework.data.mongodb.core.convert.MongoConverter;
import org.springframework.data.mongodb.core.convert.MongoWriter;
+import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity;
import org.springframework.data.mongodb.core.query.Collation;
+import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.UpdateDefinition;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
@@ -31,6 +37,10 @@
* @see CollectionShardedMongoTemplate
*/
public class CollectionShardedReactiveMongoTemplate extends ShardedReactiveMongoTemplate implements CollectionShardingAssistant {
+ private static final Logger LOGGER = LoggerFactory.getLogger(CollectionShardedReactiveMongoTemplate.class);
+
+ private static final String ID_KEY = "_id";
+
public CollectionShardedReactiveMongoTemplate(MongoClient mongoClient, String databaseName, CollectionShardingOptions collectionShardingOptions) {
super(mongoClient, databaseName, collectionShardingOptions);
}
@@ -75,13 +85,32 @@ protected Mono doFindOne(String collectionName, Document query, Document
}
@Override
- protected Flux doFind(String collectionName, Document query, Document fields, Class entityClass) {
- return super.doFind(resolveCollectionNameForFindContext(collectionName, entityClass, query), query, fields, entityClass);
+ protected Flux doFind(String collectionName, Document query, Document fields, Class entityClass, FindPublisherPreparer preparer) {
+ return super.doFind(resolveCollectionNameForFindContext(collectionName, entityClass, query), query, fields, entityClass, preparer);
}
@Override
protected Flux doFindAndDelete(String collectionName, Query query, Class entityClass) {
- return super.doFindAndDelete(resolveCollectionNameForDeleteContext(collectionName, entityClass, query), query, entityClass);
+ Flux flux = find(query, entityClass, collectionName);
+
+ return Flux.from(flux).collectList().filter(it -> !it.isEmpty())
+ .flatMapMany(list -> {
+ MongoPersistentEntity persistentEntity =
+ (MongoPersistentEntity) this.getConverter().getMappingContext().getPersistentEntity(entityClass);
+
+ MultiValueMap byIds = new LinkedMultiValueMap<>();
+ list.forEach(resultEntry -> {
+ byIds.add(ID_KEY, persistentEntity.getPropertyAccessor(resultEntry).getProperty(
+ persistentEntity.getIdProperty()));
+ });
+
+ Criteria[] criterias = byIds.entrySet().stream() //
+ .map(it -> Criteria.where(it.getKey()).in(it.getValue())) //
+ .toArray(Criteria[]::new);
+ return Flux.from(remove(
+ new Query(criterias.length == 1 ? criterias[0] : new Criteria().orOperator(criterias)), entityClass, collectionName))
+ .flatMap(deleteResult -> Flux.fromIterable(list));
+ });
}
@Override
@@ -109,6 +138,7 @@ public Mono> getCollection(String collectionName) {
return super.getCollection(resolveCollectionNameWithoutEntityContext(collectionName));
}
+
@Override
public Mono collectionExists(String collectionName) {
return super.collectionExists(resolveCollectionNameWithoutEntityContext(collectionName));
@@ -118,8 +148,17 @@ public Mono collectionExists(String collectionName, final String collec
return super.collectionExists(getShardingOptions().resolveCollectionName(collectionName, collectionHint));
}
+ private Mono> getCollectionWithoutHintResolution(String collectionName) {
+ return super.getCollection(collectionName);
+ }
+
@Override
protected Mono> doCreateCollection(String collectionName, CreateCollectionOptions collectionOptions) {
- return super.doCreateCollection(resolveCollectionNameWithoutEntityContext(collectionName), collectionOptions);
+ String resolvedCollectionName = resolveCollectionNameWithoutEntityContext(collectionName);
+ return createMono(db -> db.createCollection(resolvedCollectionName, collectionOptions)).doOnSuccess(it -> {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Created collection [{}]", collectionName);
+ }
+ }).then(getCollectionWithoutHintResolution(resolvedCollectionName));
}
}
diff --git a/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/FindFromDatabaseIterable.java b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/FindFromDatabaseIterable.java
index d1cc392c..43ca921a 100644
--- a/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/FindFromDatabaseIterable.java
+++ b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/FindFromDatabaseIterable.java
@@ -7,6 +7,7 @@
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoIterable;
import com.mongodb.client.model.Collation;
+import org.bson.BsonValue;
import org.bson.Document;
import org.bson.conversions.Bson;
@@ -125,6 +126,11 @@ public FindIterable comment(String s) {
return null;
}
+ @Override
+ public FindIterable comment(BsonValue bsonValue) {
+ return this;
+ }
+
@Override
public FindIterable hint(Bson bson) {
return null;
@@ -135,6 +141,11 @@ public FindIterable hintString(String s) {
return null;
}
+ @Override
+ public FindIterable let(Bson bson) {
+ return this;
+ }
+
@Override
public FindIterable max(Bson bson) {
return null;
diff --git a/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/FindFromDatabasePublisher.java b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/FindFromDatabasePublisher.java
new file mode 100644
index 00000000..1fb09690
--- /dev/null
+++ b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/FindFromDatabasePublisher.java
@@ -0,0 +1,178 @@
+package com.alpha.mongodb.sharding.core.fixture.db;
+
+import com.mongodb.CursorType;
+import com.mongodb.ExplainVerbosity;
+import com.mongodb.client.model.Collation;
+import com.mongodb.reactivestreams.client.FindPublisher;
+import org.bson.BsonValue;
+import org.bson.Document;
+import org.bson.conversions.Bson;
+import org.reactivestreams.Publisher;
+import org.reactivestreams.Subscriber;
+import reactor.core.publisher.Flux;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+public class FindFromDatabasePublisher implements FindPublisher {
+
+ private final List documents;
+ private final GenericMongoCursor documentGenericMongoCursor;
+
+ public FindFromDatabasePublisher(List documents) {
+ this.documents = documents;
+ this.documentGenericMongoCursor = new GenericMongoCursor<>(documents);
+ }
+
+ public FindFromDatabasePublisher(Document... documents) {
+ this(Arrays.stream(documents).collect(Collectors.toList()));
+ }
+
+
+ @Override
+ public Publisher first() {
+ return Flux.just(documents.get(0));
+ }
+
+ @Override
+ public FindPublisher filter(Bson bson) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher limit(int i) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher skip(int i) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher maxTime(long l, TimeUnit timeUnit) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher maxAwaitTime(long l, TimeUnit timeUnit) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher projection(Bson bson) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher sort(Bson bson) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher noCursorTimeout(boolean b) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher oplogReplay(boolean b) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher partial(boolean b) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher cursorType(CursorType cursorType) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher collation(Collation collation) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher comment(String s) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher comment(BsonValue bsonValue) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher hint(Bson bson) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher hintString(String s) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher let(Bson bson) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher max(Bson bson) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher min(Bson bson) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher returnKey(boolean b) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher showRecordId(boolean b) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher batchSize(int i) {
+ return this;
+ }
+
+ @Override
+ public FindPublisher allowDiskUse(Boolean aBoolean) {
+ return this;
+ }
+
+ @Override
+ public Publisher explain() {
+ return Flux.fromIterable(documents);
+ }
+
+ @Override
+ public Publisher explain(ExplainVerbosity explainVerbosity) {
+ return Flux.fromIterable(documents);
+ }
+
+ @Override
+ public Publisher explain(Class aClass) {
+ return null;
+ }
+
+ @Override
+ public Publisher explain(Class aClass, ExplainVerbosity explainVerbosity) {
+ return null;
+ }
+
+ @Override
+ public void subscribe(Subscriber super Document> subscriber) {
+ Flux.fromIterable(documents).subscribe(subscriber);
+ }
+}
diff --git a/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/ListCollectionsFromDatabaseIterable.java b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/ListCollectionsFromDatabaseIterable.java
index 914b9380..8574be65 100644
--- a/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/ListCollectionsFromDatabaseIterable.java
+++ b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/fixture/db/ListCollectionsFromDatabaseIterable.java
@@ -4,6 +4,7 @@
import com.mongodb.client.ListCollectionsIterable;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoIterable;
+import org.bson.BsonValue;
import org.bson.conversions.Bson;
import java.util.Collection;
@@ -59,4 +60,14 @@ public > A into(A objects) {
public ListCollectionsIterable batchSize(int i) {
return this;
}
+
+ @Override
+ public ListCollectionsIterable comment(String s) {
+ return this;
+ }
+
+ @Override
+ public ListCollectionsIterable comment(BsonValue bsonValue) {
+ return this;
+ }
}
diff --git a/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/template/CollectionShardedReactiveMongoTemplateTest.java b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/template/CollectionShardedReactiveMongoTemplateTest.java
new file mode 100644
index 00000000..bbed9c35
--- /dev/null
+++ b/sharding-spring/src/test/java/com/alpha/mongodb/sharding/core/template/CollectionShardedReactiveMongoTemplateTest.java
@@ -0,0 +1,721 @@
+package com.alpha.mongodb.sharding.core.template;
+
+import com.alpha.mongodb.sharding.core.callback.HintResolutionCallback;
+import com.alpha.mongodb.sharding.core.configuration.CollectionShardingOptions;
+import com.alpha.mongodb.sharding.core.exception.UnresolvableCollectionShardException;
+import com.alpha.mongodb.sharding.core.fixture.TestEntity1;
+import com.alpha.mongodb.sharding.core.fixture.TestEntity3;
+import com.alpha.mongodb.sharding.core.fixture.db.FindFromDatabasePublisher;
+import com.alpha.mongodb.sharding.core.fixture.db.ListCollectionsFromDatabaseIterable;
+import com.alpha.mongodb.sharding.core.hint.ShardingHintManager;
+import com.mongodb.client.model.DeleteOptions;
+import com.mongodb.client.model.FindOneAndDeleteOptions;
+import com.mongodb.client.model.UpdateOptions;
+import com.mongodb.client.result.InsertManyResult;
+import com.mongodb.client.result.InsertOneResult;
+import com.mongodb.client.result.UpdateResult;
+import com.mongodb.reactivestreams.client.MongoClient;
+import com.mongodb.reactivestreams.client.MongoCollection;
+import com.mongodb.reactivestreams.client.MongoDatabase;
+import lombok.Builder;
+import lombok.Data;
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.bson.BsonObjectId;
+import org.bson.Document;
+import org.bson.types.ObjectId;
+import org.junit.After;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.MockedStatic;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory;
+import org.springframework.data.mongodb.ReactiveMongoDatabaseUtils;
+import org.springframework.data.mongodb.core.MongoExceptionTranslator;
+import org.springframework.data.mongodb.core.convert.MongoConverter;
+import org.springframework.data.mongodb.core.query.BasicUpdate;
+import org.springframework.data.mongodb.core.query.Query;
+import org.springframework.data.mongodb.core.query.UpdateDefinition;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.IntStream;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyList;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockStatic;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+@RunWith(MockitoJUnitRunner.class)
+public class CollectionShardedReactiveMongoTemplateTest {
+
+ CollectionShardingOptions collectionShardingOptions =
+ CollectionShardingOptions.withIntegerStreamHints(IntStream.range(0, 3));
+
+ MockedStatic mongoDatabaseUtilsMockedStatic = mockStatic(ReactiveMongoDatabaseUtils.class);
+
+ @Test
+ public void testConstructorWithMongoClient() {
+ MongoClient mongoClient = mock(MongoClient.class);
+ CollectionShardedReactiveMongoTemplate collectionShardedMongoTemplate = new CollectionShardedReactiveMongoTemplate(
+ mongoClient, "TEST_DATABASE", collectionShardingOptions);
+ assertEquals(collectionShardingOptions, collectionShardedMongoTemplate.getShardingOptions());
+ assertNotNull(collectionShardedMongoTemplate);
+ }
+
+ @Test
+ public void testConstructorWithDatabaseFactory() {
+ ReactiveMongoDatabaseFactory databaseFactory = mock(ReactiveMongoDatabaseFactory.class);
+ when(databaseFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator());
+
+ CollectionShardedReactiveMongoTemplate collectionShardedMongoTemplate =
+ new CollectionShardedReactiveMongoTemplate(databaseFactory, collectionShardingOptions);
+ assertEquals(collectionShardingOptions, collectionShardedMongoTemplate.getShardingOptions());
+ assertNotNull(collectionShardedMongoTemplate);
+ }
+
+ @Test
+ public void testConstructorWithDatabaseFactoryAndConverter() {
+ ReactiveMongoDatabaseFactory databaseFactory = mock(ReactiveMongoDatabaseFactory.class);
+ when(databaseFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator());
+
+ CollectionShardedReactiveMongoTemplate collectionShardedMongoTemplate =
+ new CollectionShardedReactiveMongoTemplate(databaseFactory, mock(MongoConverter.class), collectionShardingOptions);
+ assertEquals(collectionShardingOptions, collectionShardedMongoTemplate.getShardingOptions());
+ assertNotNull(collectionShardedMongoTemplate);
+ }
+
+ @Test
+ public void testInsert() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate =
+ getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.insertOne(any(Document.class)))
+ .thenAnswer(invocation -> {
+ ObjectId objectId = ObjectId.get();
+ ((Document) invocation.getArgument(0)).put("_id", objectId);
+ return Flux.fromIterable(Collections.singletonList(
+ InsertOneResult.acknowledged(new BsonObjectId(objectId))));
+ });
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+
+ mongoTemplate.insert(testEntity3).block();
+ verify(testEntity3, times(1)).resolveCollectionHint();
+ }
+
+ @Test
+ public void testInsertWithShardingHintManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST1_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.insertOne(any(Document.class)))
+ .thenAnswer(invocation -> {
+ ObjectId objectId = ObjectId.get();
+ ((Document) invocation.getArgument(0)).put("_id", objectId);
+ return Flux.fromIterable(Collections.singletonList(
+ InsertOneResult.acknowledged(new BsonObjectId(objectId))));
+ });
+
+ TestEntity1 testEntity1 = spy(new TestEntity1());
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ mongoTemplate.insert(testEntity1).block();
+
+ verify(mockCollection).insertOne(any(Document.class));
+ }
+
+ @Test(expected = UnresolvableCollectionShardException.class)
+ public void testInsertWithShardingHintNotManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ TestEntity1 testEntity1 = spy(new TestEntity1());
+ mongoTemplate.insert(testEntity1);
+ }
+
+ @Test(expected = UnresolvableCollectionShardException.class)
+ public void testInsertWithCollectionShardingHintNotManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ TestEntity1 testEntity1 = spy(new TestEntity1());
+ ShardingHintManager.setDatabaseHint(String.valueOf(0));
+ mongoTemplate.insert(testEntity1);
+ }
+
+ @Test(expected = UnresolvableCollectionShardException.class)
+ public void testInsertWithCollectionShardingHintNotPassingValidation() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ TestEntity1 testEntity1 = spy(new TestEntity1());
+ ShardingHintManager.setCollectionHint(String.valueOf(4));
+ mongoTemplate.insert(testEntity1);
+ }
+
+ @Test
+ public void testInsertWithHintResolutionCallback() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration
+ .builder()
+ .registerHintResolutionCallback(true)
+ .build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.insertOne(any(Document.class)))
+ .thenAnswer(invocation -> {
+ ObjectId objectId = ObjectId.get();
+ ((Document) invocation.getArgument(0)).put("_id", objectId);
+ return Flux.fromIterable(Collections.singletonList(
+ InsertOneResult.acknowledged(new BsonObjectId(objectId))));
+ });
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+ mongoTemplate.insert(testEntity3).block();
+
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForSaveContext(testEntity3);
+ verify(testEntity3, times(1)).resolveCollectionHint();
+ verify(mockCollection).insertOne(any(Document.class));
+ }
+
+ @Test
+ public void testSave() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.insertOne(any(Document.class))).thenAnswer(invocationOnMock -> {
+ ObjectId objectId = ObjectId.get();
+ ((Document) invocationOnMock.getArgument(0)).put("_id", objectId);
+ return Flux.fromIterable(Collections.singletonList(
+ InsertOneResult.acknowledged(new BsonObjectId(objectId))));
+ });
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+ mongoTemplate.save(testEntity3).block();
+
+ verify(testEntity3, times(1)).resolveCollectionHint();
+ }
+
+ @Test
+ public void testDeleteOne() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.builder().registerHintResolutionCallback(true).build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+ when(mockCollection.deleteMany(any(Document.class), any(DeleteOptions.class))).thenReturn(Flux.empty());
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+ testEntity3.setId(ObjectId.get().toString());
+ mongoTemplate.remove(testEntity3).block();
+
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForDeleteContext(any(Document.class), eq(TestEntity3.class));
+ }
+
+ @Test
+ public void testDeleteOneWhenShardHintManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+ when(mockCollection.deleteMany(any(Document.class), any(DeleteOptions.class))).thenReturn(Flux.empty());
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+ testEntity3.setId(ObjectId.get().toString());
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ mongoTemplate.remove(testEntity3).block();
+
+ verify(mockCollection).deleteMany(any(Document.class), any(DeleteOptions.class));
+ }
+
+ @Test(expected = UnresolvableCollectionShardException.class)
+ public void testDeleteOneWhenShardHintNotSet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+ testEntity3.setId(ObjectId.get().toString());
+ mongoTemplate.remove(testEntity3);
+ }
+
+ @Test(expected = UnresolvableCollectionShardException.class)
+ public void testDeleteOneWhenCollectionShardHintNotSet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+ testEntity3.setId(ObjectId.get().toString());
+ ShardingHintManager.setDatabaseHint(String.valueOf(0));
+ mongoTemplate.remove(testEntity3);
+ }
+
+ @Test
+ public void testGetCollection() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0")).thenReturn(mockCollection);
+
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ Mono> mongoCollection = mongoTemplate.getCollection("TEST3");
+ assertEquals(mockCollection, mongoCollection.block());
+ }
+
+ @Test
+ public void testGetCollectionExists() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ when(mockMongoDatabase.listCollectionNames()).thenReturn(Flux.fromIterable(
+ new ListCollectionsFromDatabaseIterable(Collections.singletonList("TEST3_0"))));
+
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ assertTrue(mongoTemplate.collectionExists(TestEntity3.class).block());
+ }
+
+ @Test
+ public void testGetCollectionExistsWhenPassingHint() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ when(mockMongoDatabase.listCollectionNames()).thenReturn(Flux.fromIterable(
+ new ListCollectionsFromDatabaseIterable(Collections.singletonList("TEST3_0"))));
+
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ assertFalse(mongoTemplate.collectionExists("TEST3", String.valueOf(3)).block());
+ }
+
+ @Test
+ public void testCreateCollection() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+ when(mockMongoDatabase.createCollection(eq("TEST3_0"), any())).thenReturn(Mono.empty());
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0"))
+ .thenReturn(mockCollection);
+
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ mongoTemplate.createCollection(TestEntity3.class).block();
+ }
+
+ @Test
+ public void testCreateCollectionWhenLoggerDebugIsEnabled() {
+ Configurator.setLevel(CollectionShardedReactiveMongoTemplate.class.getCanonicalName(), Level.DEBUG);
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+ when(mockMongoDatabase.createCollection(eq("TEST3_0"), any())).thenReturn(Mono.empty());
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0"))
+ .thenReturn(mockCollection);
+
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ mongoTemplate.createCollection(TestEntity3.class).block();
+ }
+
+ @Test
+ public void testFindById() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.builder().registerHintResolutionCallback(true).build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+
+ when(mockCollection.find(any(Document.class), eq(Document.class)))
+ .thenReturn(new FindFromDatabasePublisher(Collections.singletonList(documentFound)));
+
+ Mono testEntity3Mono = mongoTemplate.findById(ObjectId.get(), TestEntity3.class);
+ TestEntity3 testEntity3 = testEntity3Mono.block();
+ assertNotNull(testEntity3);
+ assertEquals(objectId.toString(), testEntity3.getId());
+
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForFindContext(any(Document.class), eq(TestEntity3.class));
+ }
+
+ @Test
+ public void testFindByIdWhenShardingHintManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+
+ when(mockCollection.find(any(Document.class), eq(Document.class)))
+ .thenReturn(new FindFromDatabasePublisher(Collections.singletonList(documentFound)));
+
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ Mono testEntity3Mono = mongoTemplate.findById(ObjectId.get(), TestEntity3.class);
+ TestEntity3 testEntity3 = testEntity3Mono.block();
+ assertNotNull(testEntity3);
+ assertEquals(objectId.toString(), testEntity3.getId());
+ }
+
+ @Test
+ public void testUpdate() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.builder().registerHintResolutionCallback(true).build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.updateMany(any(Document.class), any(Document.class), any(UpdateOptions.class))).
+ thenReturn(Flux.just(UpdateResult.acknowledged(1L, 1L, null)));
+
+ Query updateQuery = new Query();
+ UpdateDefinition updateDefinition = new BasicUpdate(new Document()).addToSet("indexedField", "testIndexedValue");
+ mongoTemplate.updateMulti(updateQuery, updateDefinition, TestEntity3.class).block();
+
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForUpdateContext(updateQuery, updateDefinition, TestEntity3.class);
+ }
+
+ @Test
+ public void testUpdateWhenShardHintManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.updateMany(any(Document.class), any(Document.class), any(UpdateOptions.class))).
+ thenReturn(Flux.just(UpdateResult.acknowledged(1L, 1L, null)));
+
+ Query updateQuery = new Query();
+ UpdateDefinition updateDefinition = new BasicUpdate(new Document()).addToSet("indexedField", "testIndexedValue");
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ mongoTemplate.updateMulti(updateQuery, updateDefinition, TestEntity3.class).block();
+ }
+
+ @Test
+ public void testFindAndRemove() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.builder().registerHintResolutionCallback(true).build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+ when(mockCollection.findOneAndDelete(any(Document.class), any(FindOneAndDeleteOptions.class))).thenReturn(Flux.empty());
+
+ Query deleteQuery = new Query();
+ mongoTemplate.findAndRemove(deleteQuery, TestEntity3.class).block();
+
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForDeleteContext(deleteQuery.getQueryObject(), TestEntity3.class);
+ }
+
+ @Test
+ public void testFindAllAndRemove() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.builder().registerHintResolutionCallback(true).build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+ when(mockCollection.find(Document.class))
+ .thenReturn(new FindFromDatabasePublisher(Collections.singletonList(documentFound)));
+ when(mockCollection.deleteMany(any(Document.class), any(DeleteOptions.class))).thenReturn(Flux.empty());
+
+ Query deleteQuery = new Query();
+ mongoTemplate.findAllAndRemove(deleteQuery, TestEntity3.class).blockFirst();
+
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForDeleteContext(any(Document.class), eq(TestEntity3.class));
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get(), times(2))
+ .resolveHintForFindContext(any(Document.class), eq(TestEntity3.class));
+ }
+
+ @Test
+ public void testFindAllAndRemoveWhenQueryReturnsNoResults() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.builder().registerHintResolutionCallback(true).build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ when(mockCollection.find(Document.class))
+ .thenReturn(new FindFromDatabasePublisher(Collections.emptyList()));
+
+ Query deleteQuery = new Query();
+ mongoTemplate.findAllAndRemove(deleteQuery, TestEntity3.class).blockFirst();
+
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForFindContext(deleteQuery.getQueryObject(), TestEntity3.class);
+ }
+
+ @Test
+ public void testFindAllAndRemoveWhenShardHintIsManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+ when(mockCollection.find(Document.class))
+ .thenReturn(new FindFromDatabasePublisher(Collections.singletonList(documentFound)));
+ when(mockCollection.deleteMany(any(Document.class), any(DeleteOptions.class))).thenReturn(Flux.empty());
+
+ Query deleteQuery = new Query();
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ mongoTemplate.findAllAndRemove(deleteQuery, TestEntity3.class).blockFirst();
+ }
+
+
+ @Test
+ public void testFindAndRemoveWhenShardHintManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.findOneAndDelete(any(Document.class), any(FindOneAndDeleteOptions.class)))
+ .thenReturn(Flux.just(new Document()));
+
+ Query deleteQuery = new Query();
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ mongoTemplate.findAndRemove(deleteQuery, TestEntity3.class).block();
+ }
+
+ @Test
+ public void testFind() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.builder().registerHintResolutionCallback(true).build());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+ when(mockCollection.find(Document.class))
+ .thenReturn(new FindFromDatabasePublisher(Collections.singletonList(documentFound)));
+
+ Query findQuery = new Query();
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ Flux queryResultFlux = mongoTemplate.find(findQuery, TestEntity3.class);
+ TestEntity3 testEntity3 = queryResultFlux.blockFirst();
+
+ assertEquals(objectId.toString(), testEntity3.getId());
+ verify((HintResolutionCallback) collectionShardingOptions.getHintResolutionCallbacks().stream().findFirst().get())
+ .resolveHintForFindContext(findQuery.getQueryObject(), TestEntity3.class);
+ }
+
+ @Test
+ public void testFindWhenShardHintManuallySet() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+
+ ObjectId objectId = ObjectId.get();
+ Document documentFound = new Document();
+ documentFound.put("_id", objectId);
+ documentFound.put(TestEntity3.Fields.indexedField, "testIndexedFieldValue");
+ when(mockCollection.find(Document.class))
+ .thenReturn(new FindFromDatabasePublisher(Collections.singletonList(documentFound)));
+
+ Query findQuery = new Query();
+ ShardingHintManager.setCollectionHint(String.valueOf(0));
+ Flux queryResult = mongoTemplate.find(findQuery, TestEntity3.class);
+
+ TestEntity3 testEntity3 = queryResult.blockFirst();
+ assertEquals(objectId.toString(), testEntity3.getId());
+ }
+
+ @Test
+ public void testInsertBatch() {
+ CollectionShardedReactiveMongoTemplate mongoTemplate = getFixture(FixtureConfiguration.getDefault());
+
+ MongoDatabase mockMongoDatabase = mock(MongoDatabase.class);
+ mongoDatabaseUtilsMockedStatic.when(() -> ReactiveMongoDatabaseUtils.getDatabase(eq(mongoTemplate.getMongoDatabaseFactory()), any()))
+ .thenReturn(Mono.just(mockMongoDatabase));
+
+ MongoCollection mockCollection = mock(MongoCollection.class);
+ when(mockMongoDatabase.getCollection("TEST3_0", Document.class))
+ .thenReturn(mockCollection);
+ when(mockCollection.insertMany(anyList()))
+ .thenAnswer(invocation -> {
+ ObjectId objectId = ObjectId.get();
+ ((List) invocation.getArgument(0)).get(0).put("_id", objectId);
+ return Flux.fromIterable(Collections.singletonList(
+ InsertManyResult.acknowledged(
+ Collections.singletonMap(0, new BsonObjectId(objectId)))));
+ });
+
+ TestEntity3 testEntity3 = spy(new TestEntity3());
+ Flux persistedEntityListFlux =
+ mongoTemplate.insert(Collections.singletonList(testEntity3), TestEntity3.class);
+
+ persistedEntityListFlux.blockFirst();
+
+ verify(testEntity3, times(1)).resolveCollectionHint();
+ verify(mockCollection).insertMany(any());
+ }
+
+ @After
+ public void teardown() {
+ ShardingHintManager.clear();
+ mongoDatabaseUtilsMockedStatic.close();
+ }
+
+ private CollectionShardedReactiveMongoTemplate getFixture(FixtureConfiguration fixtureConfiguration) {
+ if (fixtureConfiguration.isRegisterHintResolutionCallback()) {
+ collectionShardingOptions.setHintResolutionCallbacks(Collections.singleton(
+ spy(new TestEntity3.TestEntity3CollectionHintResolutionCallback())));
+ }
+
+ ReactiveMongoDatabaseFactory databaseFactory = mock(ReactiveMongoDatabaseFactory.class);
+ databaseFactory.getMongoDatabase("TEST_DB");
+ when(databaseFactory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator());
+
+ CollectionShardedReactiveMongoTemplate collectionShardedMongoTemplate = new CollectionShardedReactiveMongoTemplate(databaseFactory, collectionShardingOptions);
+ assertEquals(collectionShardingOptions, collectionShardedMongoTemplate.getShardingOptions());
+ assertNotNull(collectionShardedMongoTemplate);
+
+ return collectionShardedMongoTemplate;
+ }
+
+ @Data
+ @Builder
+ private static class FixtureConfiguration {
+ private boolean registerHintResolutionCallback = false;
+
+ private static FixtureConfiguration getDefault() {
+ return builder().build();
+ }
+ }
+}
\ No newline at end of file
diff --git a/sharding-spring/src/test/resources/log4j2-test.xml b/sharding-spring/src/test/resources/log4j2-test.xml
new file mode 100644
index 00000000..19a48558
--- /dev/null
+++ b/sharding-spring/src/test/resources/log4j2-test.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file