diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java index 9e66e259b..298d9bb31 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsUnitTests.java @@ -18,13 +18,18 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.List; +import java.util.function.BiConsumer; + import org.bson.Document; +import org.bson.conversions.Bson; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; + import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; @@ -37,6 +42,8 @@ import org.springframework.data.mongodb.core.query.Collation; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.CreateIndexOptions; +import com.mongodb.client.model.IndexModel; import com.mongodb.client.model.IndexOptions; /** @@ -64,7 +71,7 @@ public class DefaultIndexOperationsUnitTests { when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(any(), any(Class.class))).thenReturn(collection); - when(collection.createIndex(any(), any(IndexOptions.class))).thenReturn("OK"); + when(collection.createIndexes(anyList(), any(CreateIndexOptions.class))).thenReturn(List.of("OK")); this.mappingContext = new MongoMappingContext(); this.converter = spy(new MappingMongoConverter(new DefaultDbRefResolver(factory), mappingContext)); @@ -76,7 +83,7 @@ public class DefaultIndexOperationsUnitTests { indexOpsFor(Jedi.class).ensureIndex(new Index("name", Direction.DESC)); - verify(collection).createIndex(eq(new Document("firstname", -1)), any()); + verifyCreateIndex((keys, options) -> assertThat(keys).isEqualTo(new Document("firstname", -1))); } @Test // DATAMONGO-1854 @@ -84,10 +91,7 @@ public class DefaultIndexOperationsUnitTests { indexOpsFor(Jedi.class).ensureIndex(new Index("firstname", Direction.DESC)); - ArgumentCaptor options = ArgumentCaptor.forClass(IndexOptions.class); - verify(collection).createIndex(any(), options.capture()); - - assertThat(options.getValue().getCollation()).isNull(); + verifyCreateIndex((keys, options) -> assertThat(options.getCollation()).isNull()); } @Test // DATAMONGO-1854 @@ -95,11 +99,8 @@ public class DefaultIndexOperationsUnitTests { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC)); - ArgumentCaptor options = ArgumentCaptor.forClass(IndexOptions.class); - verify(collection).createIndex(any(), options.capture()); - - assertThat(options.getValue().getCollation()) - .isEqualTo(com.mongodb.client.model.Collation.builder().locale("de_AT").build()); + verifyCreateIndex((keys, options) -> assertThat(options.getCollation()) + .isEqualTo(com.mongodb.client.model.Collation.builder().locale("de_AT").build())); } @Test // DATAMONGO-1854 @@ -107,11 +108,8 @@ public class DefaultIndexOperationsUnitTests { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC).collation(Collation.of("en_US"))); - ArgumentCaptor options = ArgumentCaptor.forClass(IndexOptions.class); - verify(collection).createIndex(any(), options.capture()); - - assertThat(options.getValue().getCollation()) - .isEqualTo(com.mongodb.client.model.Collation.builder().locale("en_US").build()); + verifyCreateIndex((keys, options) -> assertThat(options.getCollation()) + .isEqualTo(com.mongodb.client.model.Collation.builder().locale("en_US").build())); } @Test // DATAMONGO-1183 @@ -119,7 +117,7 @@ public class DefaultIndexOperationsUnitTests { indexOpsFor(Jedi.class).ensureIndex(HashedIndex.hashed("name")); - verify(collection).createIndex(eq(new Document("firstname", "hashed")), any()); + verifyCreateIndex((keys, options) -> assertThat(keys).isEqualTo(new Document("firstname", "hashed"))); } @Test // GH-4698 @@ -131,6 +129,16 @@ public class DefaultIndexOperationsUnitTests { verify(db).getCollection(eq("foo"), any(Class.class)); } + private void verifyCreateIndex(BiConsumer consumer) { + + ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); + + verify(collection).createIndexes(captor.capture(), any()); + + IndexModel indexModel = captor.getValue().get(0); + consumer.accept(indexModel.getKeys(), indexModel.getOptions()); + } + private DefaultIndexOperations indexOpsFor(Class type) { return new DefaultIndexOperations(template, template.getCollectionName(type), type); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java index 195952dbe..a866ae3ed 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsUnitTests.java @@ -20,7 +20,11 @@ import static org.mockito.Mockito.*; import reactor.core.publisher.Mono; +import java.util.List; +import java.util.function.BiConsumer; + import org.bson.Document; +import org.bson.conversions.Bson; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -28,6 +32,7 @@ import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import org.reactivestreams.Publisher; + import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.convert.MappingMongoConverter; @@ -38,13 +43,18 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.query.Collation; +import com.mongodb.client.model.CreateIndexOptions; +import com.mongodb.client.model.IndexModel; import com.mongodb.client.model.IndexOptions; import com.mongodb.reactivestreams.client.MongoCollection; import com.mongodb.reactivestreams.client.MongoDatabase; /** + * Unit tests for {@link DefaultReactiveIndexOperations}. + * * @author Christoph Strobl * @author Mathieu Ouellet + * @author Mark Paluch */ @ExtendWith(MockitoExtension.class) public class DefaultReactiveIndexOperationsUnitTests { @@ -66,7 +76,7 @@ public class DefaultReactiveIndexOperationsUnitTests { when(factory.getMongoDatabase()).thenReturn(Mono.just(db)); when(factory.getExceptionTranslator()).thenReturn(exceptionTranslator); when(db.getCollection(any(), any(Class.class))).thenReturn(collection); - when(collection.createIndex(any(), any(IndexOptions.class))).thenReturn(publisher); + when(collection.createIndexes(anyList(), any(CreateIndexOptions.class))).thenReturn(publisher); this.mappingContext = new MongoMappingContext(); this.converter = spy(new MappingMongoConverter(NoOpDbRefResolver.INSTANCE, mappingContext)); @@ -78,10 +88,7 @@ public class DefaultReactiveIndexOperationsUnitTests { indexOpsFor(Jedi.class).ensureIndex(new Index("firstname", Direction.DESC)).subscribe(); - ArgumentCaptor options = ArgumentCaptor.forClass(IndexOptions.class); - verify(collection).createIndex(any(), options.capture()); - - assertThat(options.getValue().getCollation()).isNull(); + verifyCreateIndex((keys, options) -> assertThat(options.getCollation()).isNull()); } @Test // DATAMONGO-1854 @@ -89,11 +96,8 @@ public class DefaultReactiveIndexOperationsUnitTests { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC)).subscribe(); - ArgumentCaptor options = ArgumentCaptor.forClass(IndexOptions.class); - verify(collection).createIndex(any(), options.capture()); - - assertThat(options.getValue().getCollation()) - .isEqualTo(com.mongodb.client.model.Collation.builder().locale("de_AT").build()); + verifyCreateIndex((keys, options) -> assertThat(options.getCollation()) + .isEqualTo(com.mongodb.client.model.Collation.builder().locale("de_AT").build())); } @Test // DATAMONGO-1854 @@ -102,11 +106,19 @@ public class DefaultReactiveIndexOperationsUnitTests { indexOpsFor(Sith.class).ensureIndex(new Index("firstname", Direction.DESC).collation(Collation.of("en_US"))) .subscribe(); - ArgumentCaptor options = ArgumentCaptor.forClass(IndexOptions.class); - verify(collection).createIndex(any(), options.capture()); - assertThat(options.getValue().getCollation()) - .isEqualTo(com.mongodb.client.model.Collation.builder().locale("en_US").build()); + verifyCreateIndex((keys, options) -> assertThat(options.getCollation()) + .isEqualTo(com.mongodb.client.model.Collation.builder().locale("en_US").build())); + } + + private void verifyCreateIndex(BiConsumer consumer) { + + ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); + + verify(collection).createIndexes(captor.capture(), any()); + + IndexModel indexModel = captor.getValue().get(0); + consumer.accept(indexModel.getKeys(), indexModel.getOptions()); } private DefaultReactiveIndexOperations indexOpsFor(Class type) { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java index 71837d780..e3b76afdc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/MongoPersistentEntityIndexCreatorUnitTests.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.*; import java.util.Collections; import java.util.Date; +import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; @@ -46,6 +47,8 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentProperty; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; +import com.mongodb.client.model.CreateIndexOptions; +import com.mongodb.client.model.IndexModel; import com.mongodb.client.model.IndexOptions; /** @@ -67,16 +70,14 @@ public class MongoPersistentEntityIndexCreatorUnitTests { private @Mock MongoCollection collection; private MongoTemplate mongoTemplate; - private ArgumentCaptor keysCaptor; - private ArgumentCaptor optionsCaptor; + private ArgumentCaptor> indexModelCaptor; private ArgumentCaptor collectionCaptor; @BeforeEach void setUp() { - keysCaptor = ArgumentCaptor.forClass(org.bson.Document.class); - optionsCaptor = ArgumentCaptor.forClass(IndexOptions.class); collectionCaptor = ArgumentCaptor.forClass(String.class); + indexModelCaptor = ArgumentCaptor.forClass(List.class); when(factory.getMongoDatabase()).thenReturn(db); when(factory.getExceptionTranslator()).thenReturn(new MongoExceptionTranslator()); @@ -84,8 +85,7 @@ public class MongoPersistentEntityIndexCreatorUnitTests { .thenReturn((MongoCollection) collection); mongoTemplate = new MongoTemplate(factory); - - when(collection.createIndex(keysCaptor.capture(), optionsCaptor.capture())).thenReturn("OK"); + when(collection.createIndexes(indexModelCaptor.capture(), any(CreateIndexOptions.class))).thenReturn(List.of("OK")); } @Test @@ -95,10 +95,12 @@ public class MongoPersistentEntityIndexCreatorUnitTests { new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); - assertThat(keysCaptor.getValue()).isNotNull().containsKey("fieldname"); - assertThat(optionsCaptor.getValue().getName()).isEqualTo("indexName"); - assertThat(optionsCaptor.getValue().isBackground()).isFalse(); - assertThat(optionsCaptor.getValue().getExpireAfter(TimeUnit.SECONDS)).isNull(); + IndexModel indexModel = indexModelCaptor.getValue().get(0); + + assertThat(indexModel.getKeys().toBsonDocument()).isNotNull().containsKey("fieldname"); + assertThat(indexModel.getOptions().getName()).isEqualTo("indexName"); + assertThat(indexModel.getOptions().isBackground()).isFalse(); + assertThat(indexModel.getOptions().getExpireAfter(TimeUnit.SECONDS)).isNull(); } @Test @@ -135,10 +137,12 @@ public class MongoPersistentEntityIndexCreatorUnitTests { MongoMappingContext mappingContext = prepareMappingContext(AnotherPerson.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); - assertThat(keysCaptor.getValue()).isNotNull().containsKey("lastname"); - assertThat(optionsCaptor.getValue().getName()).isEqualTo("lastname"); - assertThat(optionsCaptor.getValue().isBackground()).isTrue(); - assertThat(optionsCaptor.getValue().getExpireAfter(TimeUnit.SECONDS)).isNull(); + IndexModel indexModel = indexModelCaptor.getValue().get(0); + + assertThat(indexModel.getKeys().toBsonDocument()).isNotNull().containsKey("lastname"); + assertThat(indexModel.getOptions().getName()).isEqualTo("lastname"); + assertThat(indexModel.getOptions().isBackground()).isTrue(); + assertThat(indexModel.getOptions().getExpireAfter(TimeUnit.SECONDS)).isNull(); } @Test // DATAMONGO-544 @@ -147,8 +151,10 @@ public class MongoPersistentEntityIndexCreatorUnitTests { MongoMappingContext mappingContext = prepareMappingContext(Milk.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); - assertThat(keysCaptor.getValue()).isNotNull().containsKey("expiry"); - assertThat(optionsCaptor.getValue().getExpireAfter(TimeUnit.SECONDS)).isEqualTo(60); + IndexModel indexModel = indexModelCaptor.getValue().get(0); + + assertThat(indexModel.getKeys().toBsonDocument()).isNotNull().containsKey("expiry"); + assertThat(indexModel.getOptions().getExpireAfter(TimeUnit.SECONDS)).isEqualTo(60); } @Test // DATAMONGO-899 @@ -157,9 +163,11 @@ public class MongoPersistentEntityIndexCreatorUnitTests { MongoMappingContext mappingContext = prepareMappingContext(Wrapper.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); - assertThat(keysCaptor.getValue()).isEqualTo(new org.bson.Document("company.address.location", "2d")); + IndexModel indexModel = indexModelCaptor.getValue().get(0); + + assertThat(indexModel.getKeys()).isEqualTo(new org.bson.Document("company.address.location", "2d")); - IndexOptions opts = optionsCaptor.getValue(); + IndexOptions opts = indexModel.getOptions(); assertThat(opts.getName()).isEqualTo("company.address.location"); assertThat(opts.getMin()).isCloseTo(-180d, offset(0d)); assertThat(opts.getMax()).isCloseTo(180d, offset(0d)); @@ -172,8 +180,10 @@ public class MongoPersistentEntityIndexCreatorUnitTests { MongoMappingContext mappingContext = prepareMappingContext(EntityWithGeneratedIndexName.class); new MongoPersistentEntityIndexCreator(mappingContext, mongoTemplate); - assertThat(keysCaptor.getValue()).doesNotContainKey("name").containsKey("lastname"); - assertThat(optionsCaptor.getValue().getName()).isNull(); + IndexModel indexModel = indexModelCaptor.getValue().get(0); + + assertThat(indexModel.getKeys().toBsonDocument()).doesNotContainKey("name").containsKey("lastname"); + assertThat(indexModel.getOptions().getName()).isNull(); } @Test // DATAMONGO-367 @@ -203,8 +213,8 @@ public class MongoPersistentEntityIndexCreatorUnitTests { @Test // DATAMONGO-1125 void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrityConcerns() { - doThrow(new MongoException(6, "HostUnreachable")).when(collection).createIndex(any(org.bson.Document.class), - any(IndexOptions.class)); + doThrow(new MongoException(6, "HostUnreachable")).when(collection).createIndexes(anyList(), + any(CreateIndexOptions.class)); MongoMappingContext mappingContext = prepareMappingContext(Person.class); @@ -215,8 +225,7 @@ public class MongoPersistentEntityIndexCreatorUnitTests { @Test // DATAMONGO-1125 void createIndexShouldNotConvertUnknownExceptionTypes() { - doThrow(new ClassCastException("o_O")).when(collection).createIndex(any(org.bson.Document.class), - any(IndexOptions.class)); + doThrow(new ClassCastException("o_O")).when(collection).createIndexes(anyList(), any(CreateIndexOptions.class)); MongoMappingContext mappingContext = prepareMappingContext(Person.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java index 3ff07ecf7..eb8a9d489 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/ReactiveMongoPersistentEntityIndexCreatorUnitTests.java @@ -22,6 +22,7 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.util.Collections; +import java.util.List; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeEach; @@ -42,6 +43,8 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import com.mongodb.MongoException; +import com.mongodb.client.model.CreateIndexOptions; +import com.mongodb.client.model.IndexModel; import com.mongodb.client.model.IndexOptions; import com.mongodb.reactivestreams.client.MongoCollection; import com.mongodb.reactivestreams.client.MongoDatabase; @@ -62,6 +65,7 @@ public class ReactiveMongoPersistentEntityIndexCreatorUnitTests { @Mock MongoDatabase db; @Mock MongoCollection collection; + private ArgumentCaptor> indexModelCaptor; private ArgumentCaptor keysCaptor; private ArgumentCaptor optionsCaptor; private ArgumentCaptor collectionCaptor; @@ -79,8 +83,11 @@ public class ReactiveMongoPersistentEntityIndexCreatorUnitTests { keysCaptor = ArgumentCaptor.forClass(org.bson.Document.class); optionsCaptor = ArgumentCaptor.forClass(IndexOptions.class); collectionCaptor = ArgumentCaptor.forClass(String.class); + indexModelCaptor = ArgumentCaptor.forClass(List.class); when(collection.createIndex(keysCaptor.capture(), optionsCaptor.capture())).thenReturn(Mono.just("OK")); + when(collection.createIndexes(indexModelCaptor.capture(), any(CreateIndexOptions.class))) + .thenReturn(Mono.just("OK")); } @Test // DATAMONGO-1928 @@ -94,16 +101,18 @@ public class ReactiveMongoPersistentEntityIndexCreatorUnitTests { publisher.as(StepVerifier::create).verifyComplete(); - assertThat(keysCaptor.getValue()).isNotNull().containsKey("fieldname"); - assertThat(optionsCaptor.getValue().getName()).isEqualTo("indexName"); - assertThat(optionsCaptor.getValue().isBackground()).isFalse(); - assertThat(optionsCaptor.getValue().getExpireAfter(TimeUnit.SECONDS)).isNull(); + IndexModel indexModel = indexModelCaptor.getValue().get(0); + + assertThat(indexModel.getKeys().toBsonDocument()).isNotNull().containsKey("fieldname"); + assertThat(indexModel.getOptions().getName()).isEqualTo("indexName"); + assertThat(indexModel.getOptions().isBackground()).isFalse(); + assertThat(indexModel.getOptions().getExpireAfter(TimeUnit.SECONDS)).isNull(); } @Test // DATAMONGO-1928 void createIndexShouldUsePersistenceExceptionTranslatorForNonDataIntegrityConcerns() { - when(collection.createIndex(any(org.bson.Document.class), any(IndexOptions.class))) + when(collection.createIndexes(indexModelCaptor.capture(), any(CreateIndexOptions.class))) .thenReturn(Mono.error(new MongoException(6, "HostUnreachable"))); MongoMappingContext mappingContext = prepareMappingContext(Person.class); @@ -116,7 +125,7 @@ public class ReactiveMongoPersistentEntityIndexCreatorUnitTests { @Test // DATAMONGO-1928 void createIndexShouldNotConvertUnknownExceptionTypes() { - when(collection.createIndex(any(org.bson.Document.class), any(IndexOptions.class))) + when(collection.createIndexes(any(List.class), any(CreateIndexOptions.class))) .thenReturn(Mono.error(new ClassCastException("o_O"))); MongoMappingContext mappingContext = prepareMappingContext(Person.class);