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 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