From 8029acb3fb800ee91efe8c62c422b99bff4086ec Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Thu, 27 Feb 2020 13:19:58 +0100 Subject: [PATCH] DATAMONGO-2481 - Improve build time. Introduce Junit Jupiter extensions. Flush collections instead of dropping them. Apply cursor timeout to change stream and capped collections in tests. Original pull request: #838. --- .../core/messaging/ChangeStreamRequest.java | 43 ++- .../core/messaging/ChangeStreamTask.java | 5 + .../core/messaging/SubscriptionRequest.java | 12 + .../core/messaging/TailableCursorTask.java | 6 + .../java/ConfigClassInDefaultPackage.java | 8 + .../ReactiveTransactionIntegrationTests.java | 7 + .../config/AbstractIntegrationTests.java | 8 + .../AbstractMongoConfigurationUnitTests.java | 1 + ...uditingViaJavaConfigRepositoriesTests.java | 19 +- .../mongodb/config/ReactiveAuditingTests.java | 14 +- .../ServerAddressPropertyEditorUnitTests.java | 13 +- ...DefaultBulkOperationsIntegrationTests.java | 26 +- ...efaultIndexOperationsIntegrationTests.java | 71 ++--- .../DefaultReactiveIndexOperationsTests.java | 76 +---- .../ExecutableFindOperationSupportTests.java | 19 +- ...ExecutableRemoveOperationSupportTests.java | 16 +- ...ExecutableUpdateOperationSupportTests.java | 17 +- .../mongodb/core/JsonSchemaQueryTests.java | 15 +- .../core/MongoTemplateCollationTests.java | 7 + .../mongodb/core/MongoTemplateDbRefTests.java | 35 +-- .../data/mongodb/core/MongoTemplateTests.java | 170 ++++------- .../core/MongoTemplateTransactionTests.java | 7 + .../core/MongoTemplateUpdateTests.java | 26 +- .../core/MongoTemplateValidationTests.java | 7 + .../data/mongodb/core/NoExplicitIdTests.java | 11 +- .../mongodb/core/QueryByExampleTests.java | 16 +- .../ReactiveMongoTemplateCollationTests.java | 7 + .../core/ReactiveMongoTemplateTests.java | 120 ++++---- .../mongodb/core/TestMongoConfiguration.java | 7 + .../core/aggregation/AggregationTests.java | 83 ++--- .../auditing/MongoTemplateAuditingTests.java | 9 + .../ReactiveMongoTemplateAuditingTests.java | 7 + .../convert/MappingMongoConverterTests.java | 14 +- .../MappingMongoConverterUnitTests.java | 1 - .../MongoConvertersIntegrationTests.java | 23 +- .../core/geo/AbstractGeoSpatialTests.java | 14 +- .../data/mongodb/core/geo/GeoJsonTests.java | 69 ++++- .../core/index/IndexingIntegrationTests.java | 7 + .../mongodb/core/index/TextIndexTests.java | 29 +- .../core/mapping/GeoIndexedAppConfig.java | 8 + .../mongodb/core/mapping/MappingTests.java | 41 ++- .../mongodb/core/mapreduce/GroupByTests.java | 37 +-- .../core/messaging/ChangeStreamTests.java | 62 ++-- .../DefaultMessageListenerContainerTests.java | 75 +++-- .../core/messaging/TailableCursorTests.java | 6 +- .../mongodb/core/query/CriteriaTests.java | 41 +-- .../mongodb/core/query/TextQueryTests.java | 22 +- .../core/schema/MongoJsonSchemaTests.java | 2 + .../schema/ReactiveMongoJsonSchemaTests.java | 7 + .../monitor/MongoMonitorIntegrationTests.java | 15 +- .../ComplexIdRepositoryIntegrationTests.java | 9 +- ...oRepositoryTextSearchIntegrationTests.java | 56 +--- .../PersonRepositoryTransactionalTests.java | 11 +- ...RepositoriesRegistrarIntegrationTests.java | 4 +- ...ComposedRepositoryImplementationTests.java | 4 +- ...ReactiveRepositoryImplementationTests.java | 4 +- .../CustomRepositoryImplementationTests.java | 4 +- ...veQuerydslMongoPredicateExecutorTests.java | 7 + .../support/SimpleMongoRepositoryTests.java | 45 ++- ...leMongoRepositoryVersionedEntityTests.java | 10 + ...veMongoRepositoryVersionedEntityTests.java | 8 + .../test/util/MongoClientExtension.java | 37 ++- .../mongodb/test/util/MongoExtensions.java | 41 +++ .../test/util/MongoTemplateExtension.java | 147 +++++++++ .../mongodb/test/util/MongoTestTemplate.java | 144 +++++++++ .../util/MongoTestTemplateConfiguration.java | 285 ++++++++++++++++++ .../mongodb/test/util/MongoTestUtils.java | 13 +- .../test/util/ReactiveMongoTestTemplate.java | 145 +++++++++ .../data/mongodb/test/util/Template.java | 56 ++++ 69 files changed, 1659 insertions(+), 732 deletions(-) create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java create mode 100644 spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java index 71053ff0a..c4ed0687c 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamRequest.java @@ -15,6 +15,7 @@ */ package org.springframework.data.mongodb.core.messaging; +import java.time.Duration; import java.time.Instant; import org.bson.BsonValue; @@ -167,21 +168,37 @@ public class ChangeStreamRequest private final @Nullable String databaseName; private final @Nullable String collectionName; + private final @Nullable Duration maxAwaitTime; private final ChangeStreamOptions options; /** * Create new {@link ChangeStreamRequestOptions}. * + * @param databaseName can be {@literal null}. * @param collectionName can be {@literal null}. * @param options must not be {@literal null}. */ public ChangeStreamRequestOptions(@Nullable String databaseName, @Nullable String collectionName, ChangeStreamOptions options) { + this(databaseName, collectionName, null, options); + } + + /** + * Create new {@link ChangeStreamRequestOptions}. + * + * @param databaseName can be {@literal null}. + * @param collectionName can be {@literal null}. + * @param maxAwaitTime can be {@literal null}. + * @param options must not be {@literal null}. + */ + public ChangeStreamRequestOptions(@Nullable String databaseName, @Nullable String collectionName, + @Nullable Duration maxAwaitTime, ChangeStreamOptions options) { Assert.notNull(options, "Options must not be null!"); this.collectionName = collectionName; this.databaseName = databaseName; + this.maxAwaitTime = maxAwaitTime; this.options = options; } @@ -219,6 +236,15 @@ public class ChangeStreamRequest public String getDatabaseName() { return databaseName; } + + /* + * (non-Javadoc) + * @see org.springframework.data.mongodb.monitor.SubscriptionRequest.RequestOptions#maxAwaitTime() + */ + @Override + public Duration maxAwaitTime() { + return maxAwaitTime != null ? maxAwaitTime : RequestOptions.super.maxAwaitTime(); + } } /** @@ -232,6 +258,7 @@ public class ChangeStreamRequest private @Nullable String databaseName; private @Nullable String collectionName; + private @Nullable Duration maxAwaitTime; private @Nullable MessageListener, ? super T> listener; private ChangeStreamOptionsBuilder delegate = ChangeStreamOptions.builder(); @@ -417,6 +444,20 @@ public class ChangeStreamRequest return this; } + /** + * Set the cursors maximum wait time on the server (for a new Document to be emitted). + * + * @param timeout must not be {@literal null}. + * @since 3.0 + */ + public ChangeStreamRequestBuilder maxAwaitTime(Duration timeout) { + + Assert.notNull(timeout, "timeout not be null!"); + + this.maxAwaitTime = timeout; + return this; + } + /** * @return the build {@link ChangeStreamRequest}. */ @@ -425,7 +466,7 @@ public class ChangeStreamRequest Assert.notNull(listener, "MessageListener must not be null!"); return new ChangeStreamRequest<>(listener, - new ChangeStreamRequestOptions(databaseName, collectionName, delegate.build())); + new ChangeStreamRequestOptions(databaseName, collectionName, maxAwaitTime, delegate.build())); } } } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java index 2e11b86ec..81b67c210 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTask.java @@ -23,6 +23,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Set; +import java.util.concurrent.TimeUnit; import org.bson.BsonDocument; import org.bson.BsonTimestamp; @@ -135,6 +136,10 @@ class ChangeStreamTask extends CursorReadingTask, iterable = filter.isEmpty() ? db.watch(Document.class) : db.watch(filter, Document.class); } + if (!options.maxAwaitTime().isZero()) { + iterable = iterable.maxAwaitTime(options.maxAwaitTime().toMillis(), TimeUnit.MILLISECONDS); + } + if (!resumeToken.isEmpty()) { if (resumeAfter) { diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java index 7a7b2d64d..a6d1d28d2 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/SubscriptionRequest.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.core.messaging; +import java.time.Duration; + import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; import org.springframework.lang.Nullable; @@ -72,6 +74,16 @@ public interface SubscriptionRequest { @Nullable String getCollectionName(); + /** + * Get the maximum wait time (the time till the next Document is emitted) to apply when reading from the collection. + * + * @return never {@literal null}. {@link Duration#ZERO} by default. + * @since 3.0 + */ + default Duration maxAwaitTime() { + return Duration.ZERO; + } + /** * Create empty options. * diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java index 9425a64a7..f4e0c2145 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/messaging/TailableCursorTask.java @@ -15,6 +15,8 @@ */ package org.springframework.data.mongodb.core.messaging; +import java.util.concurrent.TimeUnit; + import org.bson.Document; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.convert.QueryMapper; @@ -75,6 +77,10 @@ class TailableCursorTask extends CursorReadingTask { iterable = iterable.collation(collation); } + if (!options.maxAwaitTime().isZero()) { + iterable = iterable.maxAwaitTime(options.maxAwaitTime().toMillis(), TimeUnit.MILLISECONDS); + } + return iterable.iterator(); } } diff --git a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java index 8e1175874..7316f4c2d 100644 --- a/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java +++ b/spring-data-mongodb/src/test/java/ConfigClassInDefaultPackage.java @@ -15,6 +15,9 @@ * limitations under the License. */ +import java.util.Collections; +import java.util.Set; + import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; @@ -46,4 +49,9 @@ public class ConfigClassInDefaultPackage extends AbstractMongoClientConfiguratio public MongoClient mongoClient() { return MongoClients.create(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java index 61f9bdf9f..7127c8563 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/ReactiveTransactionIntegrationTests.java @@ -23,6 +23,8 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.time.Duration; +import java.util.Collections; +import java.util.Set; import org.bson.types.ObjectId; import org.junit.jupiter.api.AfterAll; @@ -238,6 +240,11 @@ public class ReactiveTransactionIntegrationTests { public ReactiveMongoTransactionManager transactionManager(ReactiveMongoDatabaseFactory factory) { return new ReactiveMongoTransactionManager(factory); } + + @Override + protected Set> getInitialEntitySet() { + return Collections.singleton(Person.class); + } } @RequiredArgsConstructor diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java index 345551a19..29b24dd5c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractIntegrationTests.java @@ -17,6 +17,9 @@ package org.springframework.data.mongodb.config; import static org.springframework.data.mongodb.test.util.Assertions.*; +import java.util.Collections; +import java.util.Set; + import org.bson.Document; import org.junit.After; import org.junit.Before; @@ -54,6 +57,11 @@ public abstract class AbstractIntegrationTests { public MongoClient mongoClient() { return MongoTestUtils.client(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoOperations operations; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java index c811bba4b..50debf50b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AbstractMongoConfigurationUnitTests.java @@ -172,6 +172,7 @@ public class AbstractMongoConfigurationUnitTests { public MongoTypeMapper typeMapper() { return new CustomMongoTypeMapper(); } + } static class ConfigurationWithMultipleBasePackages extends AbstractMongoClientConfiguration { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java index 53d42af97..27e3b05b7 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/AuditingViaJavaConfigRepositoriesTests.java @@ -18,8 +18,11 @@ package org.springframework.data.mongodb.config; import static org.assertj.core.api.Assertions.*; import static org.mockito.Mockito.*; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; import java.util.function.Function; import org.junit.jupiter.api.BeforeEach; @@ -28,7 +31,9 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.annotation.Version; import org.springframework.data.domain.AuditorAware; import org.springframework.data.mongodb.core.AuditablePerson; @@ -68,7 +73,8 @@ public class AuditingViaJavaConfigRepositoriesTests { @Configuration @EnableMongoAuditing(auditorAwareRef = "auditorProvider") - @EnableMongoRepositories(basePackageClasses = AuditablePersonRepository.class, considerNestedRepositories = true) + @EnableMongoRepositories(basePackageClasses = AuditablePersonRepository.class, considerNestedRepositories = true, + includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = AuditablePersonRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Override @@ -86,6 +92,12 @@ public class AuditingViaJavaConfigRepositoriesTests { public AuditorAware auditorProvider() { return mock(AuditorAware.class); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>( + Arrays.asList(AuditablePerson.class, VersionedAuditablePerson.class, SimpleVersionedAuditablePerson.class)); + } } @BeforeEach @@ -212,6 +224,11 @@ public class AuditingViaJavaConfigRepositoriesTests { protected String getDatabaseName() { return "database"; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } static class VersionedAuditablePerson extends AuditablePerson { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java index 3c1d29c53..f79b88e45 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ReactiveAuditingTests.java @@ -21,7 +21,10 @@ import static org.mockito.Mockito.*; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; @@ -29,7 +32,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.annotation.Version; import org.springframework.data.domain.AuditorAware; import org.springframework.data.mongodb.core.AuditablePerson; @@ -63,7 +68,8 @@ public class ReactiveAuditingTests { @Configuration @EnableMongoAuditing(auditorAwareRef = "auditorProvider") - @EnableReactiveMongoRepositories(basePackageClasses = ReactiveAuditingTests.class, considerNestedRepositories = true) + @EnableReactiveMongoRepositories(basePackageClasses = ReactiveAuditingTests.class, considerNestedRepositories = true, + includeFilters = @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ReactiveAuditablePersonRepository.class)) static class Config extends AbstractReactiveMongoConfiguration { @Override @@ -76,6 +82,12 @@ public class ReactiveAuditingTests { return mongoClient; } + @Override + protected Set> getInitialEntitySet() { + return new HashSet<>( + Arrays.asList(AuditablePerson.class, VersionedAuditablePerson.class, SimpleVersionedAuditablePerson.class)); + } + @Bean @SuppressWarnings("unchecked") public AuditorAware auditorProvider() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java index d07ef9922..854501f60 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/config/ServerAddressPropertyEditorUnitTests.java @@ -23,8 +23,9 @@ import java.net.UnknownHostException; import java.util.Arrays; import java.util.Collection; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledIfSystemProperty; import com.mongodb.ServerAddress; @@ -38,12 +39,12 @@ public class ServerAddressPropertyEditorUnitTests { ServerAddressPropertyEditor editor; - @Before + @BeforeEach public void setUp() { editor = new ServerAddressPropertyEditor(); } - @Test(expected = IllegalArgumentException.class) // DATAMONGO-454, DATAMONGO-1062 + @Test // DATAMONGO-454, DATAMONGO-1062 public void rejectsAddressConfigWithoutASingleParsableAndResolvableServerAddress() { String unknownHost1 = "gugu.nonexistant.example.org"; @@ -51,10 +52,12 @@ public class ServerAddressPropertyEditorUnitTests { assertUnresolveableHostnames(unknownHost1, unknownHost2); - editor.setAsText(unknownHost1 + "," + unknownHost2); + assertThatExceptionOfType(IllegalArgumentException.class) + .isThrownBy(() -> editor.setAsText(unknownHost1 + "," + unknownHost2)); } @Test // DATAMONGO-454 + @EnabledIfSystemProperty(named = "user.name", matches = "jenkins") public void skipsUnparsableAddressIfAtLeastOneIsParsable() throws UnknownHostException { editor.setAsText("foo, localhost"); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java index 982c2374a..3a04a67a0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultBulkOperationsIntegrationTests.java @@ -23,10 +23,9 @@ import java.util.List; import java.util.Optional; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.dao.DuplicateKeyException; import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.DefaultBulkOperations.BulkOperationContext; @@ -36,9 +35,10 @@ import org.springframework.data.mongodb.core.mapping.MongoPersistentEntity; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.data.util.Pair; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoBulkWriteException; import com.mongodb.WriteConcern; @@ -52,21 +52,17 @@ import com.mongodb.client.MongoCollection; * @author Christoph Strobl * @author Minsu Kim */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class DefaultBulkOperationsIntegrationTests { static final String COLLECTION_NAME = "bulk_ops"; - @Autowired MongoOperations operations; + @Template(initialEntitySet = BaseDoc.class) // + static MongoTestTemplate operations; - MongoCollection collection; - - @Before + @BeforeEach public void setUp() { - - this.collection = this.operations.getCollection(COLLECTION_NAME); - this.collection.deleteMany(new Document()); + operations.flush(COLLECTION_NAME); } @Test // DATAMONGO-934 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java index 9876ba493..638a8546f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultIndexOperationsIntegrationTests.java @@ -16,27 +16,26 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; -import static org.assertj.core.api.Assumptions.*; import static org.springframework.data.mongodb.core.index.PartialIndexFilter.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import org.bson.BsonDocument; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.IndexDefinition; import org.springframework.data.mongodb.core.index.IndexInfo; +import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Collation.CaseFirst; -import org.springframework.data.util.Version; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.ObjectUtils; import com.mongodb.client.MongoCollection; @@ -49,43 +48,27 @@ import com.mongodb.client.model.IndexOptions; * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class DefaultIndexOperationsIntegrationTests { - private static final Version THREE_DOT_TWO = new Version(3, 2); - private static final Version THREE_DOT_FOUR = new Version(3, 4); - private static Version mongoVersion; + static final String COLLECTION_NAME = "default-index-operations-tests"; static final org.bson.Document GEO_SPHERE_2D = new org.bson.Document("loaction", "2dsphere"); - @Autowired MongoTemplate template; - DefaultIndexOperations indexOps; - MongoCollection collection; + @Template // + static MongoTestTemplate template; - @Before + MongoCollection collection = template.getCollection(COLLECTION_NAME); + IndexOperations indexOps = template.indexOps(COLLECTION_NAME); + + @BeforeEach public void setUp() { - - queryMongoVersionIfNecessary(); - String collectionName = this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class); - - this.collection = this.template.getDb().getCollection(collectionName, Document.class); - this.collection.dropIndexes(); - this.indexOps = new DefaultIndexOperations(template.getMongoDbFactory(), collectionName, - new QueryMapper(template.getConverter())); - } - - private void queryMongoVersionIfNecessary() { - - if (mongoVersion == null) { - Document result = template.executeCommand("{ buildInfo: 1 }"); - mongoVersion = Version.parse(result.get("version").toString()); - } + template.dropIndexes(COLLECTION_NAME); } @Test // DATAMONGO-1008 public void getIndexInfoShouldBeAbleToRead2dsphereIndex() { - collection.createIndex(GEO_SPHERE_2D); + template.getCollection(COLLECTION_NAME).createIndex(GEO_SPHERE_2D); IndexInfo info = findAndReturnIndexInfo(GEO_SPHERE_2D); assertThat(info.getIndexFields().get(0).isGeo()).isEqualTo(true); @@ -94,8 +77,6 @@ public class DefaultIndexOperationsIntegrationTests { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldApplyPartialFilterCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-criteria").on("k3y", Direction.ASC) .partial(of(where("q-t-y").gte(10))); @@ -109,12 +90,10 @@ public class DefaultIndexOperationsIntegrationTests { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldApplyPartialFilterWithMappedPropertyCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-mapped-criteria").on("k3y", Direction.ASC) .partial(of(where("quantity").gte(10))); - indexOps.ensureIndex(id); + template.indexOps(DefaultIndexOperationsIntegrationTestsSample.class).ensureIndex(id); IndexInfo info = findAndReturnIndexInfo(indexOps.getIndexInfo(), "partial-with-mapped-criteria"); assertThat(Document.parse(info.getPartialFilterExpression())) @@ -124,8 +103,6 @@ public class DefaultIndexOperationsIntegrationTests { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldApplyPartialDBOFilterCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-dbo").on("k3y", Direction.ASC) .partial(of(new org.bson.Document("qty", new org.bson.Document("$gte", 10)))); @@ -139,13 +116,10 @@ public class DefaultIndexOperationsIntegrationTests { @Test // DATAMONGO-1467, DATAMONGO-2198 public void shouldFavorExplicitMappingHintViaClass() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)).isTrue(); - IndexDefinition id = new Index().named("partial-with-inheritance").on("k3y", Direction.ASC) .partial(of(where("age").gte(10))); - indexOps = new DefaultIndexOperations(template.getMongoDbFactory(), - this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class), + indexOps = new DefaultIndexOperations(template.getMongoDbFactory(), COLLECTION_NAME, new QueryMapper(template.getConverter()), MappingToSameCollection.class); indexOps.ensureIndex(id); @@ -173,14 +147,11 @@ public class DefaultIndexOperationsIntegrationTests { @Test // DATAMONGO-1518 public void shouldCreateIndexWithCollationCorrectly() { - assumeThat(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_FOUR)).isTrue(); - IndexDefinition id = new Index().named("with-collation").on("xyz", Direction.ASC) .collation(Collation.of("de_AT").caseFirst(CaseFirst.off())); - new DefaultIndexOperations(template.getMongoDbFactory(), - this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class), - new QueryMapper(template.getConverter()), MappingToSameCollection.class); + new DefaultIndexOperations(template.getMongoDbFactory(), COLLECTION_NAME, new QueryMapper(template.getConverter()), + MappingToSameCollection.class); indexOps.ensureIndex(id); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java index 1f4dd31fa..4fe2888be 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/DefaultReactiveIndexOperationsTests.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; -import static org.junit.Assume.*; import static org.springframework.data.mongodb.core.index.PartialIndexFilter.*; import static org.springframework.data.mongodb.core.query.Criteria.*; @@ -25,14 +24,10 @@ import reactor.test.StepVerifier; import java.util.function.Predicate; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.config.AbstractReactiveMongoConfiguration; import org.springframework.data.mongodb.core.convert.QueryMapper; import org.springframework.data.mongodb.core.index.Index; import org.springframework.data.mongodb.core.index.IndexDefinition; @@ -40,71 +35,36 @@ import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Collation; import org.springframework.data.mongodb.core.query.Collation.CaseFirst; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.util.Version; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.ReactiveMongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.reactivestreams.client.MongoClient; import com.mongodb.reactivestreams.client.MongoCollection; /** * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration +@ExtendWith(MongoTemplateExtension.class) public class DefaultReactiveIndexOperationsTests { - @Configuration - static class Config extends AbstractReactiveMongoConfiguration { + @Template(initialEntitySet = DefaultIndexOperationsIntegrationTestsSample.class) + static ReactiveMongoTestTemplate template; - @Override - public MongoClient reactiveMongoClient() { - return MongoTestUtils.reactiveClient(); - } + String collectionName = template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class); - @Override - protected String getDatabaseName() { - return "index-ops-tests"; - } - } + MongoCollection collection = template.getCollection(collectionName); + DefaultReactiveIndexOperations indexOps = new DefaultReactiveIndexOperations(template, collectionName, + new QueryMapper(template.getConverter())); - private static final Version THREE_DOT_TWO = new Version(3, 2); - private static final Version THREE_DOT_FOUR = new Version(3, 4); - private static Version mongoVersion; - - @Autowired ReactiveMongoTemplate template; - - MongoCollection collection; - DefaultReactiveIndexOperations indexOps; - - @Before + @BeforeEach public void setUp() { - - queryMongoVersionIfNecessary(); - String collectionName = this.template.getCollectionName(DefaultIndexOperationsIntegrationTestsSample.class); - - this.collection = this.template.getMongoDatabase().getCollection(collectionName, Document.class); - this.indexOps = new DefaultReactiveIndexOperations(template, collectionName, - new QueryMapper(template.getConverter())); - StepVerifier.create(this.collection.dropIndexes()).verifyComplete(); } - private void queryMongoVersionIfNecessary() { - - if (mongoVersion == null) { - Document result = template.executeCommand("{ buildInfo: 1 }").block(); - mongoVersion = Version.parse(result.get("version").toString()); - } - } - @Test // DATAMONGO-1518 public void shouldCreateIndexWithCollationCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_FOUR)); - IndexDefinition id = new Index().named("with-collation").on("xyz", Direction.ASC) .collation(Collation.of("de_AT").caseFirst(CaseFirst.off())); @@ -137,8 +97,6 @@ public class DefaultReactiveIndexOperationsTests { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldApplyPartialFilterCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-criteria").on("k3y", Direction.ASC) .partial(of(where("q-t-y").gte(10))); @@ -155,8 +113,6 @@ public class DefaultReactiveIndexOperationsTests { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldApplyPartialFilterWithMappedPropertyCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-mapped-criteria").on("k3y", Direction.ASC) .partial(of(where("quantity").gte(10))); @@ -172,8 +128,6 @@ public class DefaultReactiveIndexOperationsTests { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldApplyPartialDBOFilterCorrectly() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-dbo").on("k3y", Direction.ASC) .partial(of(new org.bson.Document("qty", new org.bson.Document("$gte", 10)))); @@ -191,8 +145,6 @@ public class DefaultReactiveIndexOperationsTests { @Test // DATAMONGO-1682, DATAMONGO-2198 public void shouldFavorExplicitMappingHintViaClass() { - assumeTrue(mongoVersion.isGreaterThanOrEqualTo(THREE_DOT_TWO)); - IndexDefinition id = new Index().named("partial-with-inheritance").on("k3y", Direction.ASC) .partial(of(where("age").gte(10))); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java index 58c91e88d..0a0e3e04f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableFindOperationSupportTests.java @@ -44,10 +44,9 @@ import org.springframework.data.mongodb.core.index.GeospatialIndex; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.NearQuery; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; - -import com.mongodb.client.MongoClient; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * Integration tests for {@link ExecutableFindOperationSupport}. @@ -55,13 +54,14 @@ import com.mongodb.client.MongoClient; * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class ExecutableFindOperationSupportTests { private static final String STAR_WARS = "star-wars"; private static final String STAR_WARS_PLANETS = "star-wars-universe"; - static @Client MongoClient mongoClient; - MongoTemplate template; + + @Template(database = "executable-find-operation-support-tests", initialEntitySet = { Person.class, Planet.class }) // + static MongoTestTemplate template; Person han; Person luke; @@ -72,10 +72,7 @@ public class ExecutableFindOperationSupportTests { @BeforeEach public void setUp() { - template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableFindOperationSupportTests")); - template.dropCollection(STAR_WARS); - template.dropCollection(STAR_WARS_PLANETS); + template.flush(); template.indexOps(Planet.class).ensureIndex( new GeospatialIndex("coordinates").typed(GeoSpatialIndexType.GEO_2DSPHERE).named("planet-coordinate-idx")); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java index bbf9cabe0..cec119d49 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableRemoveOperationSupportTests.java @@ -28,10 +28,10 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.result.DeleteResult; /** @@ -40,13 +40,13 @@ import com.mongodb.client.result.DeleteResult; * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class ExecutableRemoveOperationSupportTests { private static final String STAR_WARS = "star-wars"; - static @Client MongoClient mongoClient; - MongoTemplate template; + @Template(initialEntitySet = Person.class) // + static MongoTestTemplate template; Person han; Person luke; @@ -54,9 +54,7 @@ public class ExecutableRemoveOperationSupportTests { @BeforeEach public void setUp() { - template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableRemoveOperationSupportTests")); - template.dropCollection(STAR_WARS); + template.flush(); han = new Person(); han.firstname = "han"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java index 73a52737a..712c5ce02 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ExecutableUpdateOperationSupportTests.java @@ -31,10 +31,10 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.result.UpdateResult; /** @@ -43,12 +43,13 @@ import com.mongodb.client.result.UpdateResult; * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class ExecutableUpdateOperationSupportTests { private static final String STAR_WARS = "star-wars"; - static @Client MongoClient mongoClient; - MongoTemplate template; + + @Template(initialEntitySet = { Human.class, Jedi.class, Person.class }) // + static MongoTestTemplate template; Person han; Person luke; @@ -56,9 +57,7 @@ public class ExecutableUpdateOperationSupportTests { @BeforeEach public void setUp() { - template = new MongoTemplate( - new SimpleMongoClientDatabaseFactory(mongoClient, "ExecutableUpdateOperationSupportTests")); - template.dropCollection(STAR_WARS); + template.flush(); han = new Person(); han.firstname = "han"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java index 6ad794e76..62b8efd40 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/JsonSchemaQueryTests.java @@ -31,29 +31,30 @@ import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.schema.MongoJsonSchema; import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; - -import com.mongodb.client.MongoClient; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class JsonSchemaQueryTests { public static final String DATABASE_NAME = "json-schema-query-tests"; - static @Client MongoClient client; static @Client com.mongodb.reactivestreams.client.MongoClient reactiveClient; - MongoTemplate template; + @Template(database = DATABASE_NAME, initialEntitySet = Person.class) // + static MongoTestTemplate template; + Person jellyBelly, roseSpringHeart, kazmardBoombub; @BeforeEach public void setUp() { - template = new MongoTemplate(client, DATABASE_NAME); + template.flush(); jellyBelly = new Person(); jellyBelly.id = "1"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java index ed0607f4f..95844332a 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateCollationTests.java @@ -17,8 +17,10 @@ package org.springframework.data.mongodb.core; import static org.assertj.core.api.Assertions.*; +import java.util.Collections; import java.util.List; import java.util.Locale; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -63,6 +65,11 @@ public class MongoTemplateCollationTests { protected boolean autoIndexCreation() { return false; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java index 5f779f322..74a064130 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateDbRefTests.java @@ -35,10 +35,10 @@ import org.springframework.data.mongodb.core.convert.LazyLoadingTestUtils; import org.springframework.data.mongodb.core.mapping.DBRef; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.MongoId; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.model.Filters; /** @@ -47,31 +47,24 @@ import com.mongodb.client.model.Filters; * * @author Christoph Strobl */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class MongoTemplateDbRefTests { - static @Client MongoClient mongoClient; + @Template(database = "mongo-template-dbref-tests", + initialEntitySet = { RefCycleLoadingIntoDifferentTypeRoot.class, + RefCycleLoadingIntoDifferentTypeIntermediate.class, RefCycleLoadingIntoDifferentTypeRootView.class, + WithDBRefOnRawStringId.class, WithLazyDBRefOnRawStringId.class, WithRefToAnotherDb.class, + WithLazyRefToAnotherDb.class, WithListRefToAnotherDb.class, WithLazyListRefToAnotherDb.class }) // + static MongoTestTemplate template; - MongoTemplate template; - MongoTemplate otherDbTemplate; + @Template(database = "mongo-template-dbref-tests-other-db", initialEntitySet = JustSomeType.class) // + static MongoTestTemplate otherDbTemplate; @BeforeEach public void setUp() { - template = new MongoTemplate(mongoClient, "mongo-template-dbref-tests"); - - template.dropCollection(RefCycleLoadingIntoDifferentTypeRoot.class); - template.dropCollection(RefCycleLoadingIntoDifferentTypeIntermediate.class); - template.dropCollection(RefCycleLoadingIntoDifferentTypeRootView.class); - template.dropCollection(WithDBRefOnRawStringId.class); - template.dropCollection(WithLazyDBRefOnRawStringId.class); - template.dropCollection(WithRefToAnotherDb.class); - template.dropCollection(WithLazyRefToAnotherDb.class); - template.dropCollection(WithListRefToAnotherDb.class); - template.dropCollection(WithLazyListRefToAnotherDb.class); - - otherDbTemplate = new MongoTemplate(mongoClient, "mongo-template-dbref-tests-other-db"); - otherDbTemplate.dropCollection(JustSomeType.class); + template.flush(); + otherDbTemplate.flush(); } @Test // DATAMONGO-1703 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java index 24e3feeaf..af65ca01f 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTests.java @@ -40,14 +40,11 @@ import java.util.stream.IntStream; import org.bson.types.ObjectId; import org.joda.time.DateTime; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.core.convert.converter.Converter; import org.springframework.dao.DataAccessException; import org.springframework.dao.DataIntegrityViolationException; @@ -64,13 +61,9 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mapping.MappingException; -import org.springframework.data.mapping.context.PersistentEntities; import org.springframework.data.mongodb.InvalidMongoDbApiUsageException; import org.springframework.data.mongodb.MongoDatabaseFactory; -import org.springframework.data.mongodb.core.convert.DbRefResolver; -import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; import org.springframework.data.mongodb.core.convert.LazyLoadingProxy; -import org.springframework.data.mongodb.core.convert.MappingMongoConverter; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.index.Index; @@ -78,22 +71,20 @@ import org.springframework.data.mongodb.core.index.IndexField; import org.springframework.data.mongodb.core.index.IndexInfo; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.MongoId; -import org.springframework.data.mongodb.core.mapping.MongoMappingContext; import org.springframework.data.mongodb.core.mapping.event.AbstractMongoEventListener; import org.springframework.data.mongodb.core.mapping.event.AfterSaveEvent; -import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener; import org.springframework.data.mongodb.core.mapping.event.BeforeConvertEvent; import org.springframework.data.mongodb.core.mapping.event.BeforeSaveEvent; import org.springframework.data.mongodb.core.query.BasicQuery; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; import org.springframework.data.util.CloseableIterator; import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import org.springframework.util.ClassUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.StringUtils; @@ -128,111 +119,72 @@ import com.mongodb.client.result.UpdateResult; * @author Laszlo Csontos * @author duozhilin */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoClientExtension.class) public class MongoTemplateTests { - @Autowired MongoTemplate template; - @Autowired MongoDatabaseFactory factory; + public static final String DB_NAME = "mongo-template-tests"; - ConfigurableApplicationContext context; - MongoTemplate mappingTemplate; + static @Client MongoClient client; - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); + ConfigurableApplicationContext context = new GenericApplicationContext(); - @Autowired - public void setApplicationContext(ConfigurableApplicationContext context) { + MongoTestTemplate template = new MongoTestTemplate(cfg -> { - this.context = context; + cfg.configureDatabaseFactory(it -> { - context.addApplicationListener(new PersonWithIdPropertyOfTypeUUIDListener()); + it.client(client); + it.defaultDb(DB_NAME); + }); - PersistentEntities entities = PersistentEntities.of(template.getConverter().getMappingContext()); + cfg.configureMappingContext(it -> { + it.autocreateIndex(false); + it.intitalEntitySet(AuditablePerson.class); - context.addApplicationListener(new AuditingEventListener(() -> new IsNewAwareAuditingHandler(entities))); - } + }); - @Autowired - public void setMongoClient(MongoClient mongo) throws Exception { + cfg.configureApplicationContext(it -> { + it.applicationContext(context); + it.addEventListener(new PersonWithIdPropertyOfTypeUUIDListener()); + }); - CustomConversions conversions = new MongoCustomConversions( - Arrays.asList(DateToDateTimeConverter.INSTANCE, DateTimeToDateConverter.INSTANCE)); + cfg.configureAuditing(it -> { + it.auditingHandler(IsNewAwareAuditingHandler::new); + }); + }); - MongoMappingContext mappingContext = new MongoMappingContext(); - mappingContext.setInitialEntitySet( - new HashSet<>(Arrays.asList(PersonWith_idPropertyOfTypeObjectId.class, PersonWith_idPropertyOfTypeString.class, - PersonWithIdPropertyOfTypeObjectId.class, PersonWithIdPropertyOfTypeString.class, - PersonWithIdPropertyOfTypeInteger.class, PersonWithIdPropertyOfTypeBigInteger.class, - PersonWithIdPropertyOfPrimitiveInt.class, PersonWithIdPropertyOfTypeLong.class, - PersonWithIdPropertyOfPrimitiveLong.class, PersonWithIdPropertyOfTypeUUID.class))); - mappingContext.setSimpleTypeHolder(conversions.getSimpleTypeHolder()); - mappingContext.initialize(); + MongoTestTemplate mappingTemplate = new MongoTestTemplate(cfg -> { - DbRefResolver dbRefResolver = new DefaultDbRefResolver(factory); - MappingMongoConverter mappingConverter = new MappingMongoConverter(dbRefResolver, mappingContext); - mappingConverter.setCustomConversions(conversions); - mappingConverter.afterPropertiesSet(); + cfg.configureDatabaseFactory(it -> { - this.mappingTemplate = new MongoTemplate(factory, mappingConverter); - } + it.client(client); + it.defaultDb(DB_NAME); + }); - @Before - public void setUp() { + cfg.configureConversion(it -> { + it.customConverters(DateToDateTimeConverter.INSTANCE, DateTimeToDateConverter.INSTANCE); + }); - cleanDb(); + cfg.configureMappingContext(it -> { + it.autocreateIndex(false); + }); - this.mappingTemplate.setApplicationContext(context); - } + cfg.configureApplicationContext(it -> { + it.applicationContext(new GenericApplicationContext()); + it.addEventListener(new PersonWithIdPropertyOfTypeUUIDListener()); + }); + }); - @After + MongoDatabaseFactory factory = template.getMongoDbFactory(); + + @AfterEach public void cleanUp() { - cleanDb(); - } - protected void cleanDb() { + template.flush(); + template.flush("collection", "personX", "findandreplace"); + + mappingTemplate.flush(); + template.dropCollection(Person.class); - template.dropCollection(PersonWithAList.class); - template.dropCollection(PersonWith_idPropertyOfTypeObjectId.class); - template.dropCollection(PersonWith_idPropertyOfTypeString.class); - template.dropCollection(PersonWithIdPropertyOfTypeObjectId.class); - template.dropCollection(PersonWithIdPropertyOfTypeString.class); - template.dropCollection(PersonWithIdPropertyOfTypeInteger.class); - template.dropCollection(PersonWithIdPropertyOfTypeBigInteger.class); - template.dropCollection(PersonWithIdPropertyOfPrimitiveInt.class); - template.dropCollection(PersonWithIdPropertyOfTypeLong.class); - template.dropCollection(PersonWithIdPropertyOfPrimitiveLong.class); - template.dropCollection(PersonWithIdPropertyOfTypeUUID.class); - template.dropCollection(PersonWithVersionPropertyOfTypeInteger.class); - template.dropCollection(TestClass.class); - template.dropCollection(Sample.class); - template.dropCollection(MyPerson.class); - template.dropCollection(TypeWithFieldAnnotation.class); - template.dropCollection(TypeWithDate.class); - template.dropCollection("collection"); - template.dropCollection("personX"); - template.dropCollection("findandreplace"); - template.dropCollection(Document.class); - template.dropCollection(ObjectWith3AliasedFields.class); - template.dropCollection(ObjectWith3AliasedFieldsAndNestedAddress.class); - template.dropCollection(BaseDoc.class); - template.dropCollection(ObjectWithEnumValue.class); - template.dropCollection(DocumentWithCollection.class); - template.dropCollection(DocumentWithCollectionOfSimpleType.class); - template.dropCollection(DocumentWithMultipleCollections.class); - template.dropCollection(DocumentWithNestedCollection.class); - template.dropCollection(DocumentWithEmbeddedDocumentWithCollection.class); - template.dropCollection(DocumentWithNestedList.class); - template.dropCollection(DocumentWithDBRefCollection.class); - template.dropCollection(SomeContent.class); - template.dropCollection(SomeTemplate.class); - template.dropCollection(Address.class); - template.dropCollection(DocumentWithCollectionOfSamples.class); - template.dropCollection(WithGeoJson.class); - template.dropCollection(DocumentWithNestedTypeHavingStringIdProperty.class); - template.dropCollection(ImmutableAudited.class); - template.dropCollection(RawStringId.class); - template.dropCollection(Outer.class); - template.dropCollection(Message.class); } @Test @@ -408,7 +360,7 @@ public class MongoTemplateTests { @Test // DATAMONGO-746, DATAMONGO-2264 public void testReadIndexInfoForIndicesCreatedViaMongoShellCommands() throws Exception { - template.indexOps(Person.class).dropAllIndexes(); + template.dropCollection(Person.class); assertThat(template.indexOps(Person.class).getIndexInfo().isEmpty()).isTrue(); @@ -1314,6 +1266,7 @@ public class MongoTemplateTests { @Test // DATADOC-202 public void executeDocument() { + template.insert(new Person("Tom")); template.insert(new Person("Dick")); template.insert(new Person("Harry")); @@ -1487,7 +1440,7 @@ public class MongoTemplateTests { assertThat(result.get(0).getName()).isEqualTo("Oleg"); } - @Test(expected = OptimisticLockingFailureException.class) // DATAMONGO-279 + @Test // DATAMONGO-279 public void optimisticLockingHandling() { // Init version @@ -1519,7 +1472,9 @@ public class MongoTemplateTests { person.version = 0; person.firstName = "Patryk3"; - template.save(person); + final PersonWithVersionPropertyOfTypeInteger toBeSaved = person; + + assertThatExceptionOfType(OptimisticLockingFailureException.class).isThrownBy(() -> template.save(toBeSaved)); } @Test // DATAMONGO-562 @@ -1595,13 +1550,14 @@ public class MongoTemplateTests { assertThat(document.containsKey("_id")).isTrue(); } - @Test(expected = MappingException.class) // DATAMONGO-550, DATAMONGO-1730 + @Test // DATAMONGO-550, DATAMONGO-1730 public void rejectsPlainObjectWithOutExplicitCollection() { org.bson.Document document = new org.bson.Document("foo", "bar"); template.save(document, "collection"); - template.findById(document.get("_id"), org.bson.Document.class); + assertThatExceptionOfType(MappingException.class) + .isThrownBy(() -> template.findById(document.get("_id"), org.bson.Document.class)); } @Test // DATAMONGO-550 @@ -1709,7 +1665,7 @@ public class MongoTemplateTests { assertThat(person.version).isEqualTo(0L); } - @Test(expected = DuplicateKeyException.class) // DATAMONGO-622 + @Test // DATAMONGO-622 public void preventsDuplicateInsert() { template.setWriteConcern(WriteConcern.ACKNOWLEDGED); @@ -1721,7 +1677,7 @@ public class MongoTemplateTests { assertThat(person.version).isEqualTo(0); person.version = null; - template.save(person); + assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(() -> template.save(person)); } @Test // DATAMONGO-629 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java index 0c2ae519b..f612bd457 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateTransactionTests.java @@ -23,7 +23,9 @@ import static org.springframework.data.mongodb.test.util.MongoTestUtils.*; import lombok.AllArgsConstructor; import lombok.Data; +import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.bson.Document; @@ -93,6 +95,11 @@ public class MongoTemplateTransactionTests { MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java index bb777b2c1..1f85b8ee2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateUpdateTests.java @@ -27,7 +27,6 @@ import java.util.List; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.springframework.data.annotation.Id; import org.springframework.data.annotation.Version; import org.springframework.data.mongodb.core.aggregation.AggregationUpdate; @@ -39,34 +38,25 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; -import org.springframework.data.mongodb.test.util.MongoClientExtension; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; /** * @author Christoph Strobl */ -@ExtendWith({ MongoClientExtension.class }) +@ExtendWith({ MongoTemplateExtension.class }) class MongoTemplateUpdateTests { - static final String DB_NAME = "update-test"; - - static @Client MongoClient client; - - MongoTemplate template; + @Template(initialEntitySet = { Score.class, Versioned.class, Book.class }) // + static MongoTestTemplate template; @BeforeEach void setUp() { - - template = new MongoTemplate(new SimpleMongoClientDatabaseFactory(client, DB_NAME)); - - MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Score.class), client); - MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Versioned.class), client); - MongoTestUtils.createOrReplaceCollection(DB_NAME, template.getCollectionName(Book.class), client); + template.flush(); } @Test // DATAMONGO-2331 @@ -305,7 +295,7 @@ class MongoTemplateUpdateTests { } private MongoCollection collection(Class type) { - return client.getDatabase(DB_NAME).getCollection(template.getCollectionName(type)); + return template.getCollection(template.getCollectionName(type)); } @Document("scores") diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java index 4550b7d46..828573826 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/MongoTemplateValidationTests.java @@ -22,7 +22,9 @@ import static org.springframework.data.mongodb.core.validation.Validator.*; import lombok.AllArgsConstructor; import lombok.Data; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -75,6 +77,11 @@ public class MongoTemplateValidationTests { protected boolean autoIndexCreation() { return false; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java index d228f742d..1f1979b2d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/NoExplicitIdTests.java @@ -19,14 +19,18 @@ import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Collections; import java.util.Map; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.repository.MongoRepository; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @@ -50,7 +54,7 @@ public class NoExplicitIdTests { static @Client MongoClient mongoClient; @Configuration - @EnableMongoRepositories(considerNestedRepositories = true) + @EnableMongoRepositories(considerNestedRepositories = true, includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = TypeWithoutExplicitIdPropertyRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Override @@ -67,6 +71,11 @@ public class NoExplicitIdTests { protected boolean autoIndexCreation() { return false; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoOperations mongoOps; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java index 34e719dd1..bd10c900b 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/QueryByExampleTests.java @@ -33,10 +33,9 @@ import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.UntypedExampleMatcher; -import org.springframework.data.mongodb.test.util.Client; -import org.springframework.data.mongodb.test.util.MongoClientExtension; - -import com.mongodb.client.MongoClient; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * Integration tests for Query-by-example. @@ -45,19 +44,18 @@ import com.mongodb.client.MongoClient; * @author Mark Paluch * @author Oliver Gierke */ -@ExtendWith(MongoClientExtension.class) +@ExtendWith(MongoTemplateExtension.class) public class QueryByExampleTests { - static @Client MongoClient mongoClient; + @Template(initialEntitySet = Person.class) // + static MongoTestTemplate operations; - MongoOperations operations; Person p1, p2, p3; @BeforeEach public void setUp() { - operations = new MongoTemplate(mongoClient, "query-by-example"); - operations.remove(new Query(), Person.class); + operations.flush(); p1 = new Person(); p1.firstname = "bran"; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java index 53f95e070..c3541bc3e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateCollationTests.java @@ -21,7 +21,9 @@ import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import reactor.test.StepVerifier; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -61,6 +63,11 @@ public class ReactiveMongoTemplateCollationTests { protected String getDatabaseName() { return "collation-tests"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.emptySet(); + } } @Autowired ReactiveMongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java index 571f1d875..0cd95d6a4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/ReactiveMongoTemplateTests.java @@ -43,20 +43,16 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.stream.Collectors; import java.util.stream.IntStream; -import org.assertj.core.api.Assumptions; import org.bson.BsonDocument; import org.bson.BsonTimestamp; import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.context.support.GenericApplicationContext; import org.springframework.dao.DataIntegrityViolationException; import org.springframework.dao.DuplicateKeyException; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -67,6 +63,7 @@ import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.geo.Metrics; import org.springframework.data.mapping.MappingException; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; import org.springframework.data.mongodb.core.MongoTemplateTests.Address; import org.springframework.data.mongodb.core.MongoTemplateTests.PersonWithConvertedId; import org.springframework.data.mongodb.core.MongoTemplateTests.VersionedPerson; @@ -80,14 +77,15 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.core.query.Update; -import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.test.annotation.DirtiesContext; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoServerCondition; +import org.springframework.data.mongodb.test.util.ReactiveMongoTestTemplate; import com.mongodb.WriteConcern; +import com.mongodb.reactivestreams.client.MongoClient; /** * Integration test for {@link MongoTemplate}. @@ -95,34 +93,37 @@ import com.mongodb.WriteConcern; * @author Mark Paluch * @author Christoph Strobl */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:reactive-infrastructure.xml") +@ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) public class ReactiveMongoTemplateTests { - @Autowired SimpleReactiveMongoDatabaseFactory factory; - @Autowired ReactiveMongoTemplate template; - @Autowired ConfigurableApplicationContext context; - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); + public static final String DB_NAME = "reactive-mongo-template-tests"; + static @Client MongoClient client; - @Before + ConfigurableApplicationContext context = new GenericApplicationContext(); + ReactiveMongoTestTemplate template = new ReactiveMongoTestTemplate(cfg -> { + + cfg.configureDatabaseFactory(it -> { + + it.client(client); + it.defaultDb(DB_NAME); + }); + + cfg.configureApplicationContext(it -> { + it.applicationContext(context); + }); + }); + + ReactiveMongoDatabaseFactory factory = template.getDatabaseFactory(); + + @AfterEach public void setUp() { - Flux.merge(template.dropCollection("people"), // - template.dropCollection("personX"), // - template.dropCollection("collection"), // - template.dropCollection(Person.class), // - template.dropCollection(Venue.class), // - template.dropCollection(PersonWithAList.class), // - template.dropCollection(PersonWithIdPropertyOfTypeObjectId.class), // - template.dropCollection(PersonWithVersionPropertyOfTypeInteger.class), // - template.dropCollection(Sample.class), // - template.dropCollection(MyPerson.class)) // - .as(StepVerifier::create).verifyComplete(); + template.flush().as(StepVerifier::create).verifyComplete(); + template.flush("people", "collection").as(StepVerifier::create).verifyComplete(); + template.dropCollection(Person.class).as(StepVerifier::create).verifyComplete(); + template.dropCollection("personX").as(StepVerifier::create).verifyComplete(); } - @After - public void cleanUp() {} - @Test // DATAMONGO-1444 public void insertSetsId() { @@ -952,7 +953,7 @@ public class ReactiveMongoTemplateTests { assertThat(dbObject.containsKey("_id")).isTrue(); } - @Test(expected = MappingException.class) // DATAMONGO-1444, DATAMONGO-1730 + @Test // DATAMONGO-1444, DATAMONGO-1730 public void rejectsPlainObjectWithOutExplicitCollection() { Document dbObject = new Document("foo", "bar"); @@ -962,9 +963,8 @@ public class ReactiveMongoTemplateTests { .expectNextCount(1) // .verifyComplete(); - template.findById(dbObject.get("_id"), Document.class) // - .as(StepVerifier::create) // - .verifyError(MappingException.class); + assertThatExceptionOfType(MappingException.class) + .isThrownBy(() -> template.findById(dbObject.get("_id"), Document.class)); } @Test // DATAMONGO-1444 @@ -1363,11 +1363,10 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeEmittedCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1396,11 +1395,10 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeConvertedCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1429,11 +1427,10 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeFilteredCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1463,10 +1460,9 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-1803 + @EnableIfReplicaSetAvailable public void mapsReservedWordsCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1506,11 +1502,10 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-1803 - @Ignore("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @Disabled("Heavily relying on timing assumptions. Cannot test message resumption properly. Too much race for too little time in between.") + @EnableIfReplicaSetAvailable public void changeStreamEventsShouldBeResumedCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1586,7 +1581,6 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-2189 - @DirtiesContext public void afterSaveEventContainsSavedObjectUsingInsert() { AtomicReference saved = createAfterSaveReference(); @@ -1602,7 +1596,6 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-2189 - @DirtiesContext public void afterSaveEventContainsSavedObjectUsingInsertAll() { AtomicReference saved = createAfterSaveReference(); @@ -1618,11 +1611,10 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-2012 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") + @EnableIfReplicaSetAvailable public void watchesDatabaseCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); template.createCollection("personX").as(StepVerifier::create).expectNextCount(1).verifyComplete(); @@ -1660,11 +1652,10 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-2012, DATAMONGO-2113 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") + @EnableIfReplicaSetAvailable public void resumesAtTimestampCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); @@ -1711,11 +1702,10 @@ public class ReactiveMongoTemplateTests { } @Test // DATAMONGO-2115 - @MongoVersion(asOf = "4.0") + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") + @EnableIfReplicaSetAvailable public void resumesAtBsonTimestampCorrectly() throws InterruptedException { - Assumptions.assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - template.createCollection(Person.class).as(StepVerifier::create).expectNextCount(1).verifyComplete(); BlockingQueue> documents = new LinkedBlockingQueue<>(100); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java index 8d5017c7a..9a9cd95e9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/TestMongoConfiguration.java @@ -16,7 +16,9 @@ package org.springframework.data.mongodb.core; import java.util.ArrayList; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.springframework.context.annotation.Bean; import org.springframework.core.convert.converter.Converter; @@ -54,4 +56,9 @@ public class TestMongoConfiguration extends AbstractMongoClientConfiguration { converters.add(new org.springframework.data.mongodb.core.PersonWriteConverter()); return new MongoCustomConversions(converters); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java index 06a068dc2..33e9fdb34 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/aggregation/AggregationTests.java @@ -38,15 +38,12 @@ import org.bson.Document; import org.joda.time.DateTime; import org.joda.time.DateTimeZone; import org.joda.time.LocalDateTime; -import org.junit.After; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.ClassPathResource; import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; @@ -69,14 +66,16 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.repository.Person; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.data.util.CloseableIterator; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; import com.mongodb.MongoException; import com.mongodb.client.MongoCollection; +import com.mongodb.client.model.InsertOneModel; +import com.mongodb.client.model.WriteModel; /** * Tests for {@link MongoTemplate#aggregate(Aggregation, Class, Class)}. @@ -91,8 +90,7 @@ import com.mongodb.client.MongoCollection; * @author Sergey Shcherbakov * @author Minsu Kim */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class AggregationTests { private static final String INPUT_COLLECTION = "aggregation_test_collection"; @@ -100,43 +98,29 @@ public class AggregationTests { private static boolean initialized = false; - @Autowired MongoTemplate mongoTemplate; + @Template // + static MongoTestTemplate mongoTemplate; - @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); - - @Before + @BeforeEach public void setUp() { cleanDb(); initSampleDataIfNecessary(); } - @After + @AfterEach public void cleanUp() { cleanDb(); } private void cleanDb() { + mongoTemplate.flush(Product.class, UserWithLikes.class, DATAMONGO753.class, Data.class, DATAMONGO788.class, + User.class, Person.class, Reservation.class, Venue.class, MeterData.class, LineItem.class, InventoryItem.class, + Sales.class, Sales2.class, Employee.class, Art.class, Venue.class); + mongoTemplate.dropCollection(INPUT_COLLECTION); - mongoTemplate.dropCollection(Product.class); - mongoTemplate.dropCollection(UserWithLikes.class); - mongoTemplate.dropCollection(DATAMONGO753.class); - mongoTemplate.dropCollection(Data.class); - mongoTemplate.dropCollection(DATAMONGO788.class); - mongoTemplate.dropCollection(User.class); - mongoTemplate.dropCollection(Person.class); - mongoTemplate.dropCollection(Reservation.class); - mongoTemplate.dropCollection(Venue.class); - mongoTemplate.dropCollection(MeterData.class); - mongoTemplate.dropCollection(LineItem.class); - mongoTemplate.dropCollection(InventoryItem.class); - mongoTemplate.dropCollection(Sales.class); - mongoTemplate.dropCollection(Sales2.class); - mongoTemplate.dropCollection(Employee.class); - mongoTemplate.dropCollection(Art.class); mongoTemplate.dropCollection("personQueryTemp"); - mongoTemplate.dropCollection(Venue.class); } /** @@ -149,20 +133,19 @@ public class AggregationTests { if (!initialized) { - LOGGER.debug("Server uses MongoDB Version: {}", mongoVersion); - mongoTemplate.dropCollection(ZipInfo.class); mongoTemplate.execute(ZipInfo.class, new CollectionCallback() { @Override public Void doInCollection(MongoCollection collection) throws MongoException, DataAccessException { + List> docs = new ArrayList<>(); Scanner scanner = null; try { scanner = new Scanner(new BufferedInputStream(new ClassPathResource("zips.json").getInputStream())); while (scanner.hasNextLine()) { String zipInfoRecord = scanner.nextLine(); - collection.insertOne(Document.parse(zipInfoRecord)); + docs.add(new InsertOneModel<>(Document.parse(zipInfoRecord))); } } catch (Exception e) { if (scanner != null) { @@ -171,6 +154,7 @@ public class AggregationTests { throw new RuntimeException("Could not load mongodb sample dataset!", e); } + collection.bulkWrite(docs); return null; } }); @@ -305,7 +289,6 @@ public class AggregationTests { } @Test // DATAMONGO-1391 - @MongoVersion(asOf = "3.2") public void shouldUnwindWithIndex() { MongoCollection coll = mongoTemplate.getCollection(INPUT_COLLECTION); @@ -332,7 +315,6 @@ public class AggregationTests { } @Test // DATAMONGO-1391 - @MongoVersion(asOf = "3.2") public void shouldUnwindPreserveEmpty() { MongoCollection coll = mongoTemplate.getCollection(INPUT_COLLECTION); @@ -521,7 +503,7 @@ public class AggregationTests { /* //complex mongodb aggregation framework example from https://docs.mongodb.org/manual/tutorial/aggregation-examples/#largest-and-smallest-cities-by-state - + db.zipcodes.aggregate( { $group: { @@ -952,7 +934,6 @@ public class AggregationTests { } @Test // DATAMONGO-774 - @MongoVersion(asOf = "2.4") public void stringExpressionsInProjectionExample() { Product product = new Product("P1", "A", 1.99, 3, 0.05, 0.19); @@ -1051,7 +1032,6 @@ public class AggregationTests { } @Test // DATAMONGO-774 - @MongoVersion(asOf = "2.4") public void shouldPerformDateProjectionOperatorsCorrectly() throws ParseException { Data data = new Data(); @@ -1078,7 +1058,6 @@ public class AggregationTests { } @Test // DATAMONGO-774 - @MongoVersion(asOf = "2.4") public void shouldPerformStringProjectionOperatorsCorrectly() throws ParseException { Data data = new Data(); @@ -1115,7 +1094,6 @@ public class AggregationTests { } @Test // DATAMONGO-1550 - @MongoVersion(asOf = "3.4") public void shouldPerformReplaceRootOperatorCorrectly() throws ParseException { Data data = new Data(); @@ -1263,7 +1241,6 @@ public class AggregationTests { } @Test // DATAMONGO-960 - @MongoVersion(asOf = "2.6") public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabled() { createUserWithLikesDocuments(); @@ -1287,7 +1264,6 @@ public class AggregationTests { } @Test // DATAMONGO-1637 - @MongoVersion(asOf = "2.6") public void returnFiveMostCommonLikesAggregationFrameworkExampleWithSortOnDiskOptionEnabledWhileStreaming() { createUserWithLikesDocuments(); @@ -1314,7 +1290,6 @@ public class AggregationTests { } @Test // DATAMONGO-960 - @MongoVersion(asOf = "2.6") public void returnFiveMostCommonLikesShouldReturnStageExecutionInformationWithExplainOptionEnabled() { createUserWithLikesDocuments(); @@ -1333,7 +1308,6 @@ public class AggregationTests { } @Test // DATAMONGO-954, DATAMONGO-2264 - @MongoVersion(asOf = "2.6") public void shouldSupportReturningCurrentAggregationRoot() { mongoTemplate.save(new Person("p1_first", "p1_last", 25)); @@ -1359,7 +1333,6 @@ public class AggregationTests { * {@link https://stackoverflow.com/questions/24185987/using-root-inside-spring-data-mongodb-for-retrieving-whole-document} */ @Test // DATAMONGO-954, DATAMONGO-2264 - @MongoVersion(asOf = "2.6") public void shouldSupportReturningCurrentAggregationRootInReference() { mongoTemplate.save(new Reservation("0123", "42", 100)); @@ -1379,7 +1352,6 @@ public class AggregationTests { } @Test // DATAMONGO-1549 - @MongoVersion(asOf = "3.4") public void shouldApplyCountCorrectly() { mongoTemplate.save(new Reservation("0123", "42", 100)); @@ -1537,7 +1509,6 @@ public class AggregationTests { } @Test // DATAMONGO-1326 - @MongoVersion(asOf = "3.2") public void shouldLookupPeopleCorectly() { createUsersWithReferencedPersons(); @@ -1557,7 +1528,6 @@ public class AggregationTests { } @Test // DATAMONGO-1326 - @MongoVersion(asOf = "3.2") public void shouldGroupByAndLookupPeopleCorectly() { createUsersWithReferencedPersons(); @@ -1603,7 +1573,6 @@ public class AggregationTests { } @Test // DATAMONGO-1637 - @MongoVersion(asOf = "2.6") public void shouldCreateOutputCollectionWhileStreaming() { createPersonDocuments(); @@ -1626,7 +1595,6 @@ public class AggregationTests { } @Test // DATAMONGO-1637 - @MongoVersion(asOf = "2.6") public void shouldReturnDocumentsWithOutputCollectionWhileStreaming() { createPersonDocuments(); @@ -1666,7 +1634,6 @@ public class AggregationTests { } @Test // DATAMONGO-1325 - @MongoVersion(asOf = "3.2") public void shouldApplySampleCorrectly() { createUserWithLikesDocuments(); @@ -1700,7 +1667,6 @@ public class AggregationTests { } @Test // DATAMONGO-1491 - @MongoVersion(asOf = "3.2") public void filterShouldBeAppliedCorrectly() { Item item43 = Item.builder().itemId("43").quantity(2).price(2L).build(); @@ -1731,7 +1697,6 @@ public class AggregationTests { } @Test // DATAMONGO-1538 - @MongoVersion(asOf = "3.2") public void letShouldBeAppliedCorrectly() { Sales2 sales1 = Sales2.builder().id("1").price(10).tax(0.5F).applyDiscount(true).build(); @@ -1756,7 +1721,6 @@ public class AggregationTests { } @Test // DATAMONGO-1551, DATAMONGO-2264 - @MongoVersion(asOf = "3.4") public void graphLookupShouldBeAppliedCorrectly() { Employee em1 = Employee.builder().id(1).name("Dev").build(); @@ -1789,7 +1753,6 @@ public class AggregationTests { } @Test // DATAMONGO-1552 - @MongoVersion(asOf = "3.4") public void bucketShouldCollectDocumentsIntoABucket() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); @@ -1824,7 +1787,6 @@ public class AggregationTests { } @Test // DATAMONGO-1552, DATAMONGO-2437 - @MongoVersion(asOf = "3.4") public void bucketAutoShouldCollectDocumentsIntoABucket() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); @@ -1858,7 +1820,6 @@ public class AggregationTests { } @Test // DATAMONGO-1552 - @MongoVersion(asOf = "3.4") public void facetShouldCreateFacets() { Art a1 = Art.builder().id(1).title("The Pillars of Society").artist("Grosz").year(1926).price(199.99).build(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java index b8d0ed150..20289bfa2 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/MongoTemplateAuditingTests.java @@ -19,6 +19,10 @@ import static org.assertj.core.api.Assertions.*; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -61,6 +65,11 @@ public class MongoTemplateAuditingTests { protected String getDatabaseName() { return "mongo-template-audit-tests"; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>(Arrays.asList(ImmutableAuditableEntityWithVersion.class, KAuditableVersionedEntity.class)); + } } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java index 752c99cbf..46b575f35 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/auditing/ReactiveMongoTemplateAuditingTests.java @@ -23,6 +23,8 @@ import reactor.util.function.Tuples; import java.time.Duration; import java.time.Instant; import java.time.temporal.ChronoUnit; +import java.util.Collections; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -71,6 +73,11 @@ public class ReactiveMongoTemplateAuditingTests { protected String getDatabaseName() { return DB_NAME; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.emptySet(); + } } @Autowired ReactiveMongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java index dcad85638..aa4e485f0 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterTests.java @@ -31,6 +31,7 @@ import java.time.LocalTime; import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.Arrays; +import java.util.HashSet; import java.util.List; import org.bson.Document; @@ -48,6 +49,7 @@ import org.springframework.data.mongodb.test.util.MongoClientExtension; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; +import com.mongodb.client.MongoDatabase; /** * Integration tests for {@link MappingMongoConverter}. @@ -58,8 +60,11 @@ import com.mongodb.client.MongoCollection; public class MappingMongoConverterTests { public static final String DATABASE = "mapping-converter-tests"; + static @Client MongoClient client; + MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, DATABASE); + MappingMongoConverter converter; MongoMappingContext mappingContext; DbRefResolver dbRefResolver; @@ -67,12 +72,17 @@ public class MappingMongoConverterTests { @BeforeEach public void setUp() { - client.getDatabase(DATABASE).drop(); + MongoDatabase database = client.getDatabase(DATABASE); - MongoDatabaseFactory factory = new SimpleMongoClientDatabaseFactory(client, DATABASE); + database.getCollection("samples").deleteMany(new Document()); + database.getCollection("java-time-types").deleteMany(new Document()); dbRefResolver = spy(new DefaultDbRefResolver(factory)); + mappingContext = new MongoMappingContext(); + mappingContext.setInitialEntitySet(new HashSet<>( + Arrays.asList(WithLazyDBRefAsConstructorArg.class, WithLazyDBRef.class, WithJavaTimeTypes.class))); + mappingContext.setAutoIndexCreation(false); mappingContext.afterPropertiesSet(); converter = new MappingMongoConverter(dbRefResolver, mappingContext); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java index c46f599f3..7722044ba 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MappingMongoConverterUnitTests.java @@ -41,7 +41,6 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.junit.MockitoJUnitRunner; - import org.springframework.aop.framework.ProxyFactory; import org.springframework.beans.ConversionNotSupportedException; import org.springframework.beans.factory.annotation.Value; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java index 9f09d79be..aa1258cc4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/MongoConvertersIntegrationTests.java @@ -24,17 +24,16 @@ import lombok.Data; import java.util.UUID; import org.bson.types.Binary; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * Integration tests for {@link MongoConverters}. @@ -43,17 +42,17 @@ import org.springframework.test.context.junit4.SpringRunner; * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoTemplateExtension.class) public class MongoConvertersIntegrationTests { static final String COLLECTION = "converter-tests"; - @Autowired MongoOperations template; + @Template // + static MongoTestTemplate template; - @Before + @BeforeEach public void setUp() { - template.dropCollection(COLLECTION); + template.flush(COLLECTION); } @Test // DATAMONGO-422 diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java index a03e40676..d2e856d33 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/AbstractGeoSpatialTests.java @@ -19,7 +19,9 @@ import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.joda.time.LocalDate; import org.junit.After; @@ -35,9 +37,11 @@ import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; import org.springframework.data.geo.Polygon; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; +import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.TestEntities; import org.springframework.data.mongodb.core.Venue; +import org.springframework.data.mongodb.core.geo.GeoJsonTests.Venue2DSphere; import org.springframework.data.mongodb.core.query.NearQuery; import org.springframework.data.mongodb.core.query.Query; import org.springframework.data.mongodb.test.util.MongoTestUtils; @@ -67,6 +71,11 @@ public abstract class AbstractGeoSpatialTests { public MongoClient mongoClient() { return MongoTestUtils.client(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired MongoTemplate template; @@ -102,7 +111,10 @@ public abstract class AbstractGeoSpatialTests { } protected void addVenues() { - template.insertAll(TestEntities.geolocation().newYork()); + + + template.bulkOps(BulkMode.UNORDERED, Venue.class).insert(TestEntities.geolocation().newYork()).execute(); +// template.insertAll(TestEntities.geolocation().newYork()); } @Test diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java index ed9d94167..ee4164849 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/geo/GeoJsonTests.java @@ -21,15 +21,17 @@ import static org.springframework.data.mongodb.core.query.Query.*; import lombok.Data; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import org.assertj.core.data.Percentage; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; @@ -39,6 +41,7 @@ import org.springframework.data.geo.GeoResults; import org.springframework.data.geo.Metrics; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; +import org.springframework.data.mongodb.core.BulkOperations.BulkMode; import org.springframework.data.mongodb.core.CollectionCallback; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.index.GeoSpatialIndexType; @@ -54,7 +57,6 @@ import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.MongoException; -import com.mongodb.WriteConcern; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; @@ -80,6 +82,12 @@ public class GeoJsonTests { public MongoClient mongoClient() { return mongoClient; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>(Arrays.asList(Venue2DSphere.class, VenueWithDistanceField.class, OpenGeoJson.class, + DocumentWithPropertyUsingGeoJsonType.class)); + } } @Autowired MongoTemplate template; @@ -87,7 +95,13 @@ public class GeoJsonTests { @BeforeEach public void setUp() { - template.setWriteConcern(WriteConcern.JOURNALED); + // template.setWriteConcern(WriteConcern.JOURNALED); + + // createIndex(); + // addVenues(); + } + + private void createIndexAndAddVenues() { createIndex(); addVenues(); @@ -103,6 +117,8 @@ public class GeoJsonTests { @Test // DATAMONGO-1135, DATAMONGO-2264 public void geoNear() { + createIndexAndAddVenues(); + NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.KILOMETERS).num(10).maxDistance(150); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class); @@ -115,6 +131,8 @@ public class GeoJsonTests { @Test // DATAMONGO-2264 public void geoNearShouldNotOverridePropertyWithDefaultNameForCalculatedDistance/* namely "dis" */() { + createIndexAndAddVenues(); + NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.KILOMETERS).num(10).maxDistance(150); GeoResults result = template.geoNear(geoNear, VenueWithDistanceField.class); @@ -132,6 +150,8 @@ public class GeoJsonTests { @Test // DATAMONGO-2264 public void geoNearShouldAllowToReadBackCalculatedDistanceIntoTargetTypeProperty/* namely "dis" */() { + createIndexAndAddVenues(); + NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.KILOMETERS).num(10).maxDistance(150); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class, @@ -150,6 +170,7 @@ public class GeoJsonTests { @Test // DATAMONGO-1148 public void geoNearShouldReturnDistanceCorrectlyUsingGeoJson/*which is using the meters*/() { + createIndexAndAddVenues(); NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73.99171, 40.738868), Metrics.KILOMETERS).num(10) .maxDistance(0.4); @@ -165,6 +186,7 @@ public class GeoJsonTests { @Test // DATAMONGO-1348 public void geoNearShouldReturnDistanceCorrectly/*which is using the meters*/() { + createIndexAndAddVenues(); NearQuery geoNear = NearQuery.near(new Point(-73.99171, 40.738868), Metrics.KILOMETERS).num(10).maxDistance(0.4); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class); @@ -179,6 +201,7 @@ public class GeoJsonTests { @Test // DATAMONGO-1135 public void geoNearWithMiles() { + createIndexAndAddVenues(); NearQuery geoNear = NearQuery.near(new GeoJsonPoint(-73, 40), Metrics.MILES).num(10).maxDistance(93.2057); GeoResults result = template.geoNear(geoNear, Venue2DSphere.class); @@ -190,6 +213,8 @@ public class GeoJsonTests { @Test // DATAMONGO-1135 public void withinPolygon() { + createIndexAndAddVenues(); + Point first = new Point(-73.99756, 40.73083); Point second = new Point(-73.99756, 40.741404); Point third = new Point(-73.988135, 40.741404); @@ -204,6 +229,8 @@ public class GeoJsonTests { @Test // DATAMONGO-1135 public void nearPoint() { + createIndexAndAddVenues(); + GeoJsonPoint point = new GeoJsonPoint(-73.99171, 40.738868); Query query = query(where("location").near(point).maxDistance(0.01)); @@ -214,6 +241,8 @@ public class GeoJsonTests { @Test // DATAMONGO-1135 public void nearSphere() { + createIndexAndAddVenues(); + GeoJsonPoint point = new GeoJsonPoint(-73.99171, 40.738868); Query query = query(where("location").nearSphere(point).maxDistance(0.003712240453784)); @@ -335,6 +364,8 @@ public class GeoJsonTests { @Test // DATAMONGO-1110 public void nearWithMinDistance() { + createIndexAndAddVenues(); + Point point = new GeoJsonPoint(-73.99171, 40.738868); List venues = template.find(query(where("location").near(point).minDistance(0.01)), Venue2DSphere.class); @@ -345,6 +376,8 @@ public class GeoJsonTests { @Test // DATAMONGO-1110 public void nearSphereWithMinDistance() { + createIndexAndAddVenues(); + Point point = new GeoJsonPoint(-73.99171, 40.738868); List venues = template.find(query(where("location").nearSphere(point).minDistance(0.01)), Venue2DSphere.class); @@ -355,6 +388,8 @@ public class GeoJsonTests { @Test // DATAMONGO-1135 public void nearWithMinAndMaxDistance() { + createIndexAndAddVenues(); + GeoJsonPoint point = new GeoJsonPoint(-73.99171, 40.738868); Query query = query(where("location").near(point).minDistance(0.01).maxDistance(100)); @@ -444,18 +479,22 @@ public class GeoJsonTests { private void addVenues() { - template.insert(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); - template.insert(new Venue2DSphere("10gen Office", -73.99171, 40.738868)); - template.insert(new Venue2DSphere("Flatiron Building", -73.988135, 40.741404)); - template.insert(new Venue2DSphere("Players Club", -73.997812, 40.739128)); - template.insert(new Venue2DSphere("City Bakery ", -73.992491, 40.738673)); - template.insert(new Venue2DSphere("Splash Bar", -73.992491, 40.738673)); - template.insert(new Venue2DSphere("Momofuku Milk Bar", -73.985839, 40.731698)); - template.insert(new Venue2DSphere("Shake Shack", -73.98820, 40.74164)); - template.insert(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); - template.insert(new Venue2DSphere("Empire State Building", -73.98602, 40.74894)); - template.insert(new Venue2DSphere("Ulaanbaatar, Mongolia", 106.9154, 47.9245)); - template.insert(new Venue2DSphere("Maplewood, NJ", -74.2713, 40.73137)); + List venues = new ArrayList<>(); + + venues.add(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); + venues.add(new Venue2DSphere("10gen Office", -73.99171, 40.738868)); + venues.add(new Venue2DSphere("Flatiron Building", -73.988135, 40.741404)); + venues.add(new Venue2DSphere("Players Club", -73.997812, 40.739128)); + venues.add(new Venue2DSphere("City Bakery ", -73.992491, 40.738673)); + venues.add(new Venue2DSphere("Splash Bar", -73.992491, 40.738673)); + venues.add(new Venue2DSphere("Momofuku Milk Bar", -73.985839, 40.731698)); + venues.add(new Venue2DSphere("Shake Shack", -73.98820, 40.74164)); + venues.add(new Venue2DSphere("Penn Station", -73.99408, 40.75057)); + venues.add(new Venue2DSphere("Empire State Building", -73.98602, 40.74894)); + venues.add(new Venue2DSphere("Ulaanbaatar, Mongolia", 106.9154, 47.9245)); + venues.add(new Venue2DSphere("Maplewood, NJ", -74.2713, 40.73137)); + + template.bulkOps(BulkMode.UNORDERED, Venue2DSphere.class).insert(venues).execute(); } protected void createIndex() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java index 31dfbc0f0..acfab7bfb 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/IndexingIntegrationTests.java @@ -25,8 +25,10 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; @@ -88,6 +90,11 @@ public class IndexingIntegrationTests { TimeoutResolver myTimeoutResolver() { return new TimeoutResolver("11s"); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @AfterEach diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java index 8f15f4583..2512cfcfd 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/index/TextIndexTests.java @@ -19,36 +19,37 @@ import static org.assertj.core.api.Assertions.*; import java.util.List; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.config.AbstractIntegrationTests; import org.springframework.data.mongodb.core.CollectionOptions; -import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.mapping.Language; import org.springframework.data.mongodb.core.query.Collation; - -import com.mongodb.WriteConcern; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * @author Christoph Strobl * @author Mark Paluch */ -public class TextIndexTests extends AbstractIntegrationTests { +@ExtendWith(MongoTemplateExtension.class) +public class TextIndexTests { + + @Template(initialEntitySet = TextIndexedDocumentRoot.class) + static MongoTestTemplate template; - private @Autowired MongoTemplate template; private IndexOperations indexOps; - @Before - public void setUp() throws Exception { + @BeforeEach + public void beforeEach() throws Exception { - template.setWriteConcern(WriteConcern.JOURNALED); this.indexOps = template.indexOps(TextIndexedDocumentRoot.class); - template.dropCollection(TextIndexedDocumentRoot.class); + template.dropDatabase(); + template.createCollection(TextIndexedDocumentRoot.class, CollectionOptions.empty().collation(Collation.of("de_AT"))); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java index 3aa11afd1..966f14684 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/GeoIndexedAppConfig.java @@ -15,6 +15,9 @@ */ package org.springframework.data.mongodb.core.mapping; +import java.util.Collections; +import java.util.Set; + import org.springframework.context.annotation.Bean; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.mapping.event.LoggingEventListener; @@ -47,4 +50,9 @@ public class GeoIndexedAppConfig extends AbstractMongoClientConfiguration { public LoggingEventListener mappingEventsListener() { return new LoggingEventListener(); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java index ce991c676..f6addcd40 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapping/MappingTests.java @@ -29,22 +29,26 @@ import java.util.Map; import org.bson.Document; import org.bson.types.ObjectId; -import org.junit.Test; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.dao.DataAccessException; import org.springframework.dao.DuplicateKeyException; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; import org.springframework.data.mongodb.MongoCollectionUtils; -import org.springframework.data.mongodb.config.AbstractIntegrationTests; import org.springframework.data.mongodb.core.CollectionCallback; -import org.springframework.data.mongodb.core.MongoOperations; +import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Query; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import com.mongodb.MongoException; +import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; /** @@ -53,9 +57,23 @@ import com.mongodb.client.MongoCollection; * @author Thomas Darimont * @author Mark Paluch */ -public class MappingTests extends AbstractIntegrationTests { +@ExtendWith(MongoTemplateExtension.class) +public class MappingTests { - @Autowired MongoOperations template; + static final String DB_NAME = "mapping-tests"; + + static @Client MongoClient client; + + @Template(database = DB_NAME, + initialEntitySet = { PersonWithDbRef.class, GeoLocation.class, PersonPojoStringId.class, Account.class, + DetectedCollectionWithIndex.class, Item.class, Container.class, Person.class, PersonCustomCollection1.class, + GeneratedId.class, PersonWithObjectId.class, PersonCustomIdName.class, PersonMapProperty.class }) // + static MongoTestTemplate template; + + @AfterEach + void afterEach() { + template.flush(); + } @Test public void testGeneratedId() { @@ -164,10 +182,12 @@ public class MappingTests extends AbstractIntegrationTests { assertThat(result.get(0).getAccounts()).isNotNull(); } - @Test(expected = DuplicateKeyException.class) + @Test @SuppressWarnings({ "unchecked", "rawtypes" }) public void testUniqueIndex() { + MongoTemplate template = new MongoTemplate(client, DB_NAME); + Address addr = new Address(); addr.setLines(new String[] { "1234 W. 1st Street", "Apt. 12" }); addr.setCity("Anytown"); @@ -177,7 +197,7 @@ public class MappingTests extends AbstractIntegrationTests { Person p1 = new Person(1234567890, "John", "Doe", 37, addr); Person p2 = new Person(1234567890, "Jane", "Doe", 38, addr); - template.insertAll(Arrays.asList(p1, p2)); + assertThatExceptionOfType(DuplicateKeyException.class).isThrownBy(() -> template.insertAll(Arrays.asList(p1, p2))); } @Test @@ -206,6 +226,9 @@ public class MappingTests extends AbstractIntegrationTests { @Test public void testIndexesCreatedInRightCollection() { + + MongoTemplate template = new MongoTemplate(client, DB_NAME); + CustomCollectionWithIndex ccwi = new CustomCollectionWithIndex("test"); template.insert(ccwi); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java index f5bd71ded..35cf09a0c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/mapreduce/GroupByTests.java @@ -21,18 +21,15 @@ import static org.springframework.data.mongodb.core.mapreduce.GroupBy.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import org.bson.Document; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.MongoServerCondition; import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.junit.jupiter.SpringExtension; import com.mongodb.client.MongoCollection; @@ -43,24 +40,20 @@ import com.mongodb.client.MongoCollection; * @author Oliver Gierke * @author Christoph Strobl */ -@RunWith(SpringRunner.class) +@ExtendWith({ SpringExtension.class, MongoServerCondition.class }) +@EnableIfMongoServerVersion(isLessThan = "4.1") @ContextConfiguration("classpath:infrastructure.xml") public class GroupByTests { - public static @ClassRule MongoVersionRule REQUIRES_AT_MOST_4_0 = MongoVersionRule.atMost(Version.parse("4.0.999")); + static final String GROUP_TEST_COLLECTION = "group_test_collection"; @Autowired MongoTemplate mongoTemplate; - @Before + @BeforeEach public void setUp() { cleanDb(); } - @After - public void cleanUp() { - cleanDb(); - } - protected void cleanDb() { mongoTemplate.dropCollection(mongoTemplate.getCollectionName(XObject.class)); mongoTemplate.dropCollection("group_test_collection"); @@ -96,7 +89,7 @@ public class GroupByTests { public void simpleGroupFunction() { createGroupByData(); - GroupByResults results = mongoTemplate.group("group_test_collection", GroupBy.key("x") + GroupByResults results = mongoTemplate.group(GROUP_TEST_COLLECTION, GroupBy.key("x") .initialDocument(new Document("count", 0)).reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class); @@ -109,7 +102,7 @@ public class GroupByTests { createGroupByData(); GroupByResults results = mongoTemplate .group( - "group_test_collection", GroupBy.keyFunction("function(doc) { return { x : doc.x }; }") + GROUP_TEST_COLLECTION, GroupBy.keyFunction("function(doc) { return { x : doc.x }; }") .initialDocument("{ count: 0 }").reduceFunction("function(doc, prev) { prev.count += 1 }"), XObject.class); @@ -120,7 +113,7 @@ public class GroupByTests { public void simpleGroupWithFunctionsAsResources() { createGroupByData(); - GroupByResults results = mongoTemplate.group("group_test_collection", + GroupByResults results = mongoTemplate.group(GROUP_TEST_COLLECTION, GroupBy.keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }") .reduceFunction("classpath:groupReduce.js"), XObject.class); @@ -132,7 +125,7 @@ public class GroupByTests { public void simpleGroupWithQueryAndFunctionsAsResources() { createGroupByData(); - GroupByResults results = mongoTemplate.group(where("x").gt(0), "group_test_collection", + GroupByResults results = mongoTemplate.group(where("x").gt(0), GROUP_TEST_COLLECTION, keyFunction("classpath:keyFunction.js").initialDocument("{ count: 0 }") .reduceFunction("classpath:groupReduce.js"), XObject.class); @@ -162,7 +155,7 @@ public class GroupByTests { private void createGroupByData() { - MongoCollection c = mongoTemplate.getDb().getCollection("group_test_collection", Document.class); + MongoCollection c = mongoTemplate.getDb().getCollection(GROUP_TEST_COLLECTION, Document.class); c.insertOne(new Document("x", 1)); c.insertOne(new Document("x", 1)); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java index 216e765b9..e0f255352 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/ChangeStreamTests.java @@ -25,6 +25,7 @@ import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import java.time.Duration; import java.time.Instant; import java.util.List; import java.util.concurrent.LinkedBlockingDeque; @@ -41,8 +42,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.MongoTemplate; +import org.springframework.data.mongodb.core.ChangeStreamOptions; import org.springframework.data.mongodb.core.mapping.Field; +import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions; import org.springframework.data.mongodb.core.messaging.ChangeStreamTask.ChangeStreamEventMessage; import org.springframework.data.mongodb.core.messaging.Message.MessageProperties; import org.springframework.data.mongodb.core.messaging.SubscriptionUtils.*; @@ -50,11 +52,11 @@ import org.springframework.data.mongodb.core.query.Criteria; import org.springframework.data.mongodb.core.query.Update; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; -import org.springframework.data.mongodb.test.util.MongoClientExtension; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.ReplSetClient; +import org.springframework.data.mongodb.test.util.Template; -import com.mongodb.client.MongoClient; import com.mongodb.client.model.changestream.ChangeStreamDocument; import com.mongodb.client.model.changestream.FullDocument; @@ -65,14 +67,15 @@ import com.mongodb.client.model.changestream.FullDocument; * @author Christoph Strobl * @author Mark Paluch */ -@ExtendWith({ MongoClientExtension.class }) +@ExtendWith({ MongoTemplateExtension.class }) @EnableIfReplicaSetAvailable public class ChangeStreamTests { - static @ReplSetClient MongoClient mongoClient; - static ThreadPoolExecutor executor; - MongoTemplate template; + + @Template(initialEntitySet = User.class, replicaSet = true) // + static MongoTestTemplate template; + MessageListenerContainer container; User jellyBelly; @@ -87,7 +90,6 @@ public class ChangeStreamTests { @BeforeEach public void setUp() { - template = new MongoTemplate(mongoClient, "change-stream-tests"); template.dropCollection(User.class); container = new DefaultMessageListenerContainer(template, executor); @@ -123,7 +125,8 @@ public class ChangeStreamTests { public void readsPlainDocumentMessageCorrectly() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, Document.class); awaitSubscription(subscription); @@ -148,6 +151,7 @@ public class ChangeStreamTests { ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // .collection("user") // .filter(newAggregation(match(where("age").is(7)))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -174,6 +178,7 @@ public class ChangeStreamTests { .collection("user") // .filter(newAggregation(match( new Criteria().orOperator(where("user_name").is("huffyFluffy"), where("user_name").is("jellyBelly"))))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -200,6 +205,7 @@ public class ChangeStreamTests { .publishTo(messageListener) // .filter(newAggregation(User.class, match(new Criteria().orOperator(where("userName").is("huffyFluffy"), where("userName").is("jellyBelly"))))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -209,7 +215,7 @@ public class ChangeStreamTests { template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 2); List messageBodies = messageListener.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -225,6 +231,7 @@ public class ChangeStreamTests { .collection("user") // .publishTo(messageListener) // .filter(newAggregation(User.class, match(where("operationType").is("replace")))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -240,7 +247,7 @@ public class ChangeStreamTests { template.save(replacement); - awaitMessages(messageListener); + awaitMessages(messageListener, 1); List messageBodies = messageListener.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -256,6 +263,7 @@ public class ChangeStreamTests { .collection("user") // .publishTo(messageListener) // .filter(new Document("$match", new Document("fullDocument.user_name", "sugarSplashy"))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -265,7 +273,7 @@ public class ChangeStreamTests { template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 1); List messageBodies = messageListener.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -277,7 +285,9 @@ public class ChangeStreamTests { public void resumesCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener1 = new CollectingMessageListener<>(); - Subscription subscription1 = container.register(new ChangeStreamRequest<>(messageListener1, () -> "user"), + Subscription subscription1 = container.register( + new ChangeStreamRequest<>(messageListener1, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())), User.class); awaitSubscription(subscription1); @@ -292,12 +302,12 @@ public class ChangeStreamTests { CollectingMessageListener, User> messageListener2 = new CollectingMessageListener<>(); ChangeStreamRequest subSequentRequest = ChangeStreamRequest.builder().collection("user") - .publishTo(messageListener2).resumeToken(resumeToken).build(); + .publishTo(messageListener2).resumeToken(resumeToken).maxAwaitTime(Duration.ofMillis(10)).build(); Subscription subscription2 = container.register(subSequentRequest, User.class); awaitSubscription(subscription2); - awaitMessages(messageListener2); + awaitMessages(messageListener2, 2); List messageBodies = messageListener2.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -309,7 +319,8 @@ public class ChangeStreamTests { public void readsAndConvertsMessageBodyCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, User.class); awaitSubscription(subscription); @@ -330,7 +341,8 @@ public class ChangeStreamTests { public void readsAndConvertsUpdateMessageBodyCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, User.class); awaitSubscription(subscription); @@ -349,7 +361,8 @@ public class ChangeStreamTests { public void readsOnlyDiffForUpdateWhenNotMappedToDomainType() throws InterruptedException { CollectingMessageListener, Document> messageListener = new CollectingMessageListener<>(); - ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, () -> "user"); + ChangeStreamRequest request = new ChangeStreamRequest<>(messageListener, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())); Subscription subscription = container.register(request, Document.class); awaitSubscription(subscription); @@ -372,6 +385,7 @@ public class ChangeStreamTests { ChangeStreamRequest request = ChangeStreamRequest.builder() // .collection("user") // .fullDocumentLookup(FullDocument.DEFAULT) // + .maxAwaitTime(Duration.ofMillis(10)) // .publishTo(messageListener).build(); Subscription subscription = container.register(request, User.class); @@ -395,6 +409,7 @@ public class ChangeStreamTests { ChangeStreamRequest request = ChangeStreamRequest.builder() // .collection("user") // .fullDocumentLookup(FullDocument.UPDATE_LOOKUP) // + .maxAwaitTime(Duration.ofMillis(10)) // .publishTo(messageListener).build(); Subscription subscription = container.register(request, Document.class); @@ -417,7 +432,9 @@ public class ChangeStreamTests { public void resumeAtTimestampCorrectly() throws InterruptedException { CollectingMessageListener, User> messageListener1 = new CollectingMessageListener<>(); - Subscription subscription1 = container.register(new ChangeStreamRequest<>(messageListener1, () -> "user"), + Subscription subscription1 = container.register( + new ChangeStreamRequest<>(messageListener1, + new ChangeStreamRequestOptions(null, "user", Duration.ofMillis(10), ChangeStreamOptions.builder().build())), User.class); awaitSubscription(subscription1); @@ -441,12 +458,13 @@ public class ChangeStreamTests { .collection("user") // .resumeAt(resumeAt) // .publishTo(messageListener2) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription2 = container.register(subSequentRequest, User.class); awaitSubscription(subscription2); - awaitMessages(messageListener2); + awaitMessages(messageListener2, 2); List messageBodies = messageListener2.getMessages().stream().map(Message::getBody) .collect(Collectors.toList()); @@ -461,6 +479,7 @@ public class ChangeStreamTests { ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // .collection("user") // .filter(newAggregation(User.class, match(where("address.street").is("flower street")))) // + .maxAwaitTime(Duration.ofMillis(10)) // .build(); Subscription subscription = container.register(request, User.class); @@ -495,6 +514,7 @@ public class ChangeStreamTests { ChangeStreamRequest request = ChangeStreamRequest.builder(messageListener) // .collection("user") // .filter(newAggregation(User.class, match(where("updateDescription.updatedFields.address").exists(true)))) // + .maxAwaitTime(Duration.ofMillis(10)) // .fullDocumentLookup(FullDocument.UPDATE_LOOKUP).build(); Subscription subscription = container.register(request, User.class); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java index 52d2581b5..e2cedf16e 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/DefaultMessageListenerContainerTests.java @@ -30,22 +30,21 @@ import org.bson.Document; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; - import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.dao.DataAccessException; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.core.ChangeStreamOptions; import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; +import org.springframework.data.mongodb.core.messaging.ChangeStreamRequest.ChangeStreamRequestOptions; import org.springframework.data.mongodb.core.messaging.SubscriptionRequest.RequestOptions; -import org.springframework.data.mongodb.test.util.Client; import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; -import org.springframework.data.mongodb.test.util.MongoClientExtension; import org.springframework.data.mongodb.test.util.MongoServerCondition; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.ErrorHandler; -import com.mongodb.client.MongoClient; import com.mongodb.client.MongoCollection; import com.mongodb.client.model.CreateCollectionOptions; import com.mongodb.client.model.changestream.ChangeStreamDocument; @@ -55,36 +54,31 @@ import com.mongodb.client.model.changestream.ChangeStreamDocument; * * @author Christoph Strobl */ -@ExtendWith({ MongoClientExtension.class, MongoServerCondition.class }) +@ExtendWith({ MongoTemplateExtension.class, MongoServerCondition.class }) public class DefaultMessageListenerContainerTests { - public static final String DATABASE_NAME = "change-stream-events"; - public static final String COLLECTION_NAME = "collection-1"; - public static final String COLLECTION_2_NAME = "collection-2"; + static final String DATABASE_NAME = "change-stream-events"; + static final String COLLECTION_NAME = "collection-1"; + static final String COLLECTION_2_NAME = "collection-2"; - public static final Duration TIMEOUT = Duration.ofSeconds(2); + static final Duration TIMEOUT = Duration.ofSeconds(2); - static @Client MongoClient client; + @Template(database = DATABASE_NAME, initialEntitySet = Person.class) // + static MongoTemplate template; - MongoDatabaseFactory dbFactory; - MongoCollection collection; - MongoCollection collection2; + MongoDatabaseFactory dbFactory = template.getMongoDbFactory(); + + MongoCollection collection = template.getCollection(COLLECTION_NAME); + MongoCollection collection2 = template.getCollection(COLLECTION_2_NAME); private CollectingMessageListener messageListener; - private MongoTemplate template; @BeforeEach void beforeEach() { - dbFactory = new SimpleMongoClientDatabaseFactory(client, DATABASE_NAME); - template = new MongoTemplate(dbFactory); - template.dropCollection(COLLECTION_NAME); template.dropCollection(COLLECTION_2_NAME); - collection = template.getCollection(COLLECTION_NAME); - collection2 = template.getCollection(COLLECTION_2_NAME); - messageListener = new CollectingMessageListener<>(); } @@ -94,8 +88,7 @@ public class DefaultMessageListenerContainerTests { public void shouldCollectMappedChangeStreamMessagesCorrectly() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Person.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Person.class); container.start(); awaitSubscription(subscription, TIMEOUT); @@ -126,7 +119,7 @@ public class DefaultMessageListenerContainerTests { messageListener.onMessage(message); } - }, () -> COLLECTION_NAME), Person.class, errorHandler); + }, options()), Person.class, errorHandler); container.start(); awaitSubscription(subscription, TIMEOUT); @@ -145,8 +138,7 @@ public class DefaultMessageListenerContainerTests { public void shouldNoLongerReceiveMessagesWhenContainerStopped() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Document.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Document.class); container.start(); awaitSubscription(subscription, TIMEOUT); @@ -175,8 +167,7 @@ public class DefaultMessageListenerContainerTests { Document unexpected = new Document("_id", "id-1").append("value", "foo"); collection.insertOne(unexpected); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Document.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Document.class); awaitSubscription(subscription, TIMEOUT); @@ -195,8 +186,7 @@ public class DefaultMessageListenerContainerTests { public void shouldStartReceivingMessagesWhenContainerStarts() throws InterruptedException { MessageListenerContainer container = new DefaultMessageListenerContainer(template); - Subscription subscription = container.register(new ChangeStreamRequest(messageListener, () -> COLLECTION_NAME), - Document.class); + Subscription subscription = container.register(new ChangeStreamRequest(messageListener, options()), Document.class); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); @@ -228,8 +218,8 @@ public class DefaultMessageListenerContainerTests { MessageListenerContainer container = new DefaultMessageListenerContainer(template); container.start(); - awaitSubscription( - container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), Document.class), TIMEOUT); + awaitSubscription(container.register(new TailableCursorRequest(messageListener, options()), Document.class), + TIMEOUT); collection.insertOne(new Document("_id", "id-2").append("value", "bar")); @@ -248,8 +238,8 @@ public class DefaultMessageListenerContainerTests { MessageListenerContainer container = new DefaultMessageListenerContainer(template); container.start(); - awaitSubscription( - container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), Document.class), TIMEOUT); + awaitSubscription(container.register(new TailableCursorRequest(messageListener, options()), Document.class), + TIMEOUT); collection.insertOne(new Document("_id", "id-1").append("value", "foo")); collection.insertOne(new Document("_id", "id-2").append("value", "bar")); @@ -271,7 +261,7 @@ public class DefaultMessageListenerContainerTests { collection.insertOne(new Document("_id", "id-1").append("value", "foo")); - Subscription subscription = container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), + Subscription subscription = container.register(new TailableCursorRequest(messageListener, options()), Document.class); awaitSubscription(subscription); @@ -304,7 +294,7 @@ public class DefaultMessageListenerContainerTests { try { container.start(); - Subscription subscription = container.register(new TailableCursorRequest(messageListener, () -> COLLECTION_NAME), + Subscription subscription = container.register(new TailableCursorRequest(messageListener, options()), Document.class); SubscriptionUtils.awaitSubscription(subscription); @@ -330,12 +320,12 @@ public class DefaultMessageListenerContainerTests { container.start(); CollectingMessageListener tailableListener = new CollectingMessageListener<>(); - Subscription tailableSubscription = container - .register(new TailableCursorRequest(tailableListener, () -> COLLECTION_NAME), Document.class); + Subscription tailableSubscription = container.register(new TailableCursorRequest(tailableListener, options()), + Document.class); CollectingMessageListener, Document> changeStreamListener = new CollectingMessageListener<>(); - Subscription changeStreamSubscription = container - .register(new ChangeStreamRequest(changeStreamListener, () -> COLLECTION_NAME), Document.class); + Subscription changeStreamSubscription = container.register(new ChangeStreamRequest(changeStreamListener, options()), + Document.class); awaitSubscriptions(tailableSubscription, changeStreamSubscription); @@ -390,4 +380,9 @@ public class DefaultMessageListenerContainerTests { this.firstname = firstname; } } + + static ChangeStreamRequestOptions options() { + return new ChangeStreamRequestOptions(DATABASE_NAME, COLLECTION_NAME, Duration.ofMillis(10), + ChangeStreamOptions.builder().build()); + } } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java index 2e723df5b..52fff4387 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/messaging/TailableCursorTests.java @@ -162,7 +162,7 @@ public class TailableCursorTests { template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 2); assertThat(messageListener.getMessages().stream().map(Message::getBody)).hasSize(2).doesNotContain(sugarSplashy); } @@ -183,7 +183,7 @@ public class TailableCursorTests { template.save(sugarSplashy); template.save(huffyFluffy); - awaitMessages(messageListener); + awaitMessages(messageListener, 1); assertThat(messageListener.getMessages().stream().map(Message::getBody)).hasSize(1).containsExactly(sugarSplashy); } @@ -201,7 +201,7 @@ public class TailableCursorTests { template.save(sugarSplashy); - awaitMessages(messageListener); + awaitMessages(messageListener, 3); assertThat(messageListener.getMessages().stream().map(Message::getBody)).hasSize(3).containsExactly(jellyBelly, huffyFluffy, sugarSplashy); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java index dc3e862be..783e8a0a4 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java @@ -26,29 +26,26 @@ import lombok.EqualsAndHashCode; import java.util.Arrays; import org.bson.types.Binary; -import org.junit.AfterClass; -import org.junit.Before; -import org.junit.BeforeClass; -import org.junit.Test; - +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; -import org.springframework.data.mongodb.core.MongoOperations; -import org.springframework.data.mongodb.core.MongoTemplate; -import org.springframework.data.mongodb.test.util.MongoTestUtils; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.Base64Utils; -import com.mongodb.client.MongoClient; - /** * Integration tests for {@link Criteria} usage as part of a {@link Query}. * * @author Christoph Strobl * @author Andreas Zink */ -public class CriteriaTests { +@ExtendWith(MongoTemplateExtension.class) +class CriteriaTests { - static MongoClient client; - MongoOperations ops; + @Template(initialEntitySet = { DocumentWithBitmask.class }) // + static MongoTestTemplate ops; static final DocumentWithBitmask FIFTY_FOUR/*00110110*/ = new DocumentWithBitmask("1", Integer.valueOf(54), Integer.toBinaryString(54)); @@ -59,22 +56,10 @@ public class CriteriaTests { static final DocumentWithBitmask ONE_HUNDRED_TWO/*01100110*/ = new DocumentWithBitmask("4", new Binary(Base64Utils.decodeFromString("Zg==")), "01100110"); - @BeforeClass - public static void beforeClass() { - client = MongoTestUtils.client(); - } + @BeforeEach + void beforeEach() { - @AfterClass - public static void afterClass() { - client.close(); - } - - @Before - public void setUp() { - - ops = new MongoTemplate(client, "criteria-tests"); - - ops.dropCollection(DocumentWithBitmask.class); + ops.flush(); ops.insert(FIFTY_FOUR); ops.insert(TWENTY_INT); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java index d0b4b7082..5c0dd7708 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/TextQueryTests.java @@ -23,26 +23,27 @@ import lombok.ToString; import java.util.List; import org.bson.Document; -import org.junit.Before; -import org.junit.Test; - -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.domain.PageRequest; -import org.springframework.data.mongodb.config.AbstractIntegrationTests; -import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.index.IndexDefinition; import org.springframework.data.mongodb.core.index.IndexOperations; import org.springframework.data.mongodb.core.mapping.Field; import org.springframework.data.mongodb.core.mapping.Language; import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.query.TextQueryTests.FullTextDoc.FullTextDocBuilder; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; /** * @author Christoph Strobl * @author Mark Paluch */ -public class TextQueryTests extends AbstractIntegrationTests { +@ExtendWith(MongoTemplateExtension.class) +public class TextQueryTests { private static final FullTextDoc BAKE = new FullTextDocBuilder().headline("bake").build(); private static final FullTextDoc COFFEE = new FullTextDocBuilder().subHeadline("coffee").build(); @@ -53,11 +54,14 @@ public class TextQueryTests extends AbstractIntegrationTests { private static final FullTextDoc FRENCH_MILK = new FullTextDocBuilder().headline("leche").lanugage("french").build(); private static final FullTextDoc MILK_AND_SUGAR = new FullTextDocBuilder().headline("milk and sugar").build(); - private @Autowired MongoOperations template; + @Template(initialEntitySet = FullTextDoc.class) // + static MongoTestTemplate template; - @Before + @BeforeEach public void setUp() { + template.flush(); + IndexOperations indexOps = template.indexOps(FullTextDoc.class); indexOps.dropAllIndexes(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java index 37d028c80..c489fd42c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/MongoJsonSchemaTests.java @@ -69,6 +69,8 @@ public class MongoJsonSchemaTests { protected String getDatabaseName() { return "json-schema-tests"; } + + } @Autowired MongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java index 43af21cd9..e590c529c 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/schema/ReactiveMongoJsonSchemaTests.java @@ -21,7 +21,9 @@ import lombok.Data; import reactor.test.StepVerifier; import java.time.Duration; +import java.util.Collections; import java.util.List; +import java.util.Set; import org.bson.Document; import org.junit.jupiter.api.BeforeEach; @@ -65,6 +67,11 @@ public class ReactiveMongoJsonSchemaTests { protected String getDatabaseName() { return "json-schema-tests"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.emptySet(); + } } @Autowired ReactiveMongoTemplate template; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java index fcb1cd91d..2213ed2dc 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/monitor/MongoMonitorIntegrationTests.java @@ -19,12 +19,10 @@ import static org.assertj.core.api.Assertions.*; import java.net.UnknownHostException; -import org.junit.Test; -import org.junit.runner.RunWith; - -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.data.mongodb.test.util.Client; +import org.springframework.data.mongodb.test.util.MongoClientExtension; import com.mongodb.client.MongoClient; @@ -35,11 +33,10 @@ import com.mongodb.client.MongoClient; * @author Thomas Darimont * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith(MongoClientExtension.class) public class MongoMonitorIntegrationTests { - @Autowired MongoClient mongoClient; + static @Client MongoClient mongoClient; @Test public void serverInfo() { diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java index a9488c1cf..73f53e456 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/ComplexIdRepositoryIntegrationTests.java @@ -21,12 +21,15 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @@ -47,7 +50,7 @@ public class ComplexIdRepositoryIntegrationTests { static @Client MongoClient mongoClient; @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = UserWithComplexIdRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Override @@ -60,6 +63,10 @@ public class ComplexIdRepositoryIntegrationTests { return mongoClient; } + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.emptySet(); + } } @Autowired UserWithComplexIdRepository repo; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java index f78c21a04..75c83049d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/MongoRepositoryTextSearchIntegrationTests.java @@ -20,35 +20,26 @@ import static org.assertj.core.api.Assertions.*; import java.util.Arrays; import java.util.List; -import org.junit.After; -import org.junit.Before; -import org.junit.ClassRule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.annotation.Id; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort.Direction; -import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; -import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.index.TextIndexDefinition.TextIndexDefinitionBuilder; import org.springframework.data.mongodb.core.index.TextIndexed; import org.springframework.data.mongodb.core.mapping.TextScore; import org.springframework.data.mongodb.core.query.TextCriteria; import org.springframework.data.mongodb.repository.support.MongoRepositoryFactory; -import org.springframework.data.mongodb.test.util.MongoTestUtils; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.util.Version; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; -import org.springframework.util.ClassUtils; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.util.ObjectUtils; -import com.mongodb.client.MongoClient; - /** * Integration tests for text searches on repository. * @@ -56,12 +47,9 @@ import com.mongodb.client.MongoClient; * @author Oliver Gierke * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration +@ExtendWith(MongoTemplateExtension.class) public class MongoRepositoryTextSearchIntegrationTests { - public static @ClassRule MongoVersionRule versionRule = MongoVersionRule.atLeast(new Version(2, 6, 0)); - private static final FullTextDocument PASSENGER_57 = new FullTextDocument("1", "Passenger 57", "Passenger 57 is an action film that stars Wesley Snipes and Bruce Payne."); private static final FullTextDocument DEMOLITION_MAN = new FullTextDocument("2", "Demolition Man", @@ -69,20 +57,21 @@ public class MongoRepositoryTextSearchIntegrationTests { private static final FullTextDocument DROP_ZONE = new FullTextDocument("3", "Drop Zone", "Drop Zone is an action film featuring Wesley Snipes and Gary Busey."); - @Autowired MongoTemplate template; - FullTextRepository repo; + @Template(initialEntitySet = FullTextDocument.class) // + static MongoTestTemplate template; - @Before + FullTextRepository repo = new MongoRepositoryFactory(this.template).getRepository(FullTextRepository.class); + + @BeforeEach public void setUp() { template.indexOps(FullTextDocument.class) .ensureIndex(new TextIndexDefinitionBuilder().onField("title").onField("content").build()); - this.repo = new MongoRepositoryFactory(this.template).getRepository(FullTextRepository.class); } - @After + @AfterEach public void tearDown() { - template.dropCollection(FullTextDocument.class); + template.flush(); } @Test // DATAMONGO-973 @@ -193,21 +182,6 @@ public class MongoRepositoryTextSearchIntegrationTests { repo.saveAll(Arrays.asList(PASSENGER_57, DEMOLITION_MAN, DROP_ZONE)); } - @org.springframework.context.annotation.Configuration - public static class Configuration extends AbstractMongoClientConfiguration { - - @Override - protected String getDatabaseName() { - return ClassUtils.getShortNameAsProperty(MongoRepositoryTextSearchIntegrationTests.class); - } - - @Override - public MongoClient mongoClient() { - return MongoTestUtils.client(); - } - - } - static class FullTextDocument { private @Id String id; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java index ad3e10943..ad78b5969 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/PersonRepositoryTransactionalTests.java @@ -19,7 +19,9 @@ import static org.assertj.core.api.Assertions.*; import static org.springframework.data.mongodb.test.util.MongoTestUtils.*; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import java.util.Set; import java.util.concurrent.CopyOnWriteArrayList; import org.bson.Document; @@ -29,7 +31,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.domain.Persistable; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; @@ -68,7 +72,7 @@ public class PersonRepositoryTransactionalTests { static @ReplSetClient MongoClient mongoClient; @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PersonRepository.class)) static class Config extends AbstractMongoClientConfiguration { @Bean @@ -85,6 +89,11 @@ public class PersonRepositoryTransactionalTests { MongoTransactionManager txManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return Collections.singleton(Person.class); + } } @Autowired MongoClient client; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java index 5bc6f3b54..3330c112d 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/config/MongoRepositoriesRegistrarIntegrationTests.java @@ -20,7 +20,9 @@ import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.data.mongodb.core.MongoOperations; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; @@ -39,7 +41,7 @@ import org.springframework.test.context.junit4.SpringRunner; public class MongoRepositoriesRegistrarIntegrationTests { @Configuration - @EnableMongoRepositories(basePackages = "org.springframework.data.mongodb.repository") + @EnableMongoRepositories(basePackages = "org.springframework.data.mongodb.repository", includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = PersonRepository.class)) static class Config { @Bean diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java index 0ce5f834b..6ef07a418 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/ComposedRepositoryImplementationTests.java @@ -20,7 +20,9 @@ import static org.assertj.core.api.Assertions.*; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import org.springframework.test.context.ContextConfiguration; @@ -36,7 +38,7 @@ import org.springframework.test.context.junit4.SpringRunner; public class ComposedRepositoryImplementationTests { @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = ComposedRepository.class)) @ImportResource("classpath:infrastructure.xml") static class Config {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java index 67fa8b272..a1e202a21 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomReactiveRepositoryImplementationTests.java @@ -23,7 +23,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.config.EnableReactiveMongoRepositories; @@ -40,7 +42,7 @@ import org.springframework.test.context.junit4.SpringRunner; public class CustomReactiveRepositoryImplementationTests { @Configuration - @EnableReactiveMongoRepositories + @EnableReactiveMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = CustomReactiveMongoRepository.class)) @ImportResource("classpath:reactive-infrastructure.xml") static class Config {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java index df1b859a5..b813e3e39 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/custom/CustomRepositoryImplementationTests.java @@ -23,7 +23,9 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.FilterType; import org.springframework.context.annotation.ImportResource; import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; @@ -40,7 +42,7 @@ import org.springframework.test.context.junit4.SpringRunner; public class CustomRepositoryImplementationTests { @Configuration - @EnableMongoRepositories + @EnableMongoRepositories(includeFilters=@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = CustomMongoRepository.class)) @ImportResource("classpath:infrastructure.xml") static class Config {} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java index e83d009aa..270fb9994 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/ReactiveQuerydslMongoPredicateExecutorTests.java @@ -20,7 +20,9 @@ import reactor.core.publisher.Mono; import reactor.test.StepVerifier; import java.util.Arrays; +import java.util.Collections; import java.util.LinkedHashSet; +import java.util.Set; import org.junit.After; import org.junit.Before; @@ -84,6 +86,11 @@ public class ReactiveQuerydslMongoPredicateExecutorTests { protected String getDatabaseName() { return "reactive"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.singleton(Person.class); + } } @BeforeClass diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java index 8688a5768..9cf066ace 100755 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryTests.java @@ -16,7 +16,6 @@ package org.springframework.data.mongodb.repository.support; import static org.assertj.core.api.Assertions.*; -import static org.assertj.core.api.Assumptions.*; import static org.springframework.data.domain.ExampleMatcher.*; import java.util.ArrayList; @@ -28,18 +27,15 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Autowired; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.springframework.data.domain.Example; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.ExampleMatcher.*; import org.springframework.data.geo.Point; import org.springframework.data.mongodb.MongoTransactionManager; -import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.geo.GeoJsonPoint; import org.springframework.data.mongodb.core.mapping.Document; import org.springframework.data.mongodb.core.query.Collation; @@ -48,11 +44,12 @@ import org.springframework.data.mongodb.repository.Person; import org.springframework.data.mongodb.repository.Person.Sex; import org.springframework.data.mongodb.repository.User; import org.springframework.data.mongodb.repository.query.MongoEntityInformation; -import org.springframework.data.mongodb.test.util.MongoVersion; -import org.springframework.data.mongodb.test.util.MongoVersionRule; -import org.springframework.data.mongodb.test.util.ReplicaSet; -import org.springframework.test.context.ContextConfiguration; -import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.data.mongodb.test.util.EnableIfMongoServerVersion; +import org.springframework.data.mongodb.test.util.EnableIfReplicaSetAvailable; +import org.springframework.data.mongodb.test.util.MongoServerCondition; +import org.springframework.data.mongodb.test.util.MongoTemplateExtension; +import org.springframework.data.mongodb.test.util.MongoTestTemplate; +import org.springframework.data.mongodb.test.util.Template; import org.springframework.test.util.ReflectionTestUtils; import org.springframework.transaction.support.TransactionTemplate; @@ -62,22 +59,22 @@ import org.springframework.transaction.support.TransactionTemplate; * @author Christoph Strobl * @author Mark Paluch */ -@RunWith(SpringRunner.class) -@ContextConfiguration("classpath:infrastructure.xml") +@ExtendWith({ MongoTemplateExtension.class, MongoServerCondition.class }) public class SimpleMongoRepositoryTests { - @Autowired private MongoTemplate template; - public @Rule MongoVersionRule mongoVersion = MongoVersionRule.any(); + @Template(initialEntitySet = Person.class) // + static MongoTestTemplate template; private Person oliver, dave, carter, boyd, stefan, leroi, alicia; private List all; private MongoEntityInformation personEntityInformation = new CustomizedPersonInformation(); - private SimpleMongoRepository repository; + private SimpleMongoRepository repository = new SimpleMongoRepository<>(personEntityInformation, + template); - @Before + @BeforeEach public void setUp() { - repository = new SimpleMongoRepository(personEntityInformation, template); + repository.deleteAll(); oliver = new Person("Oliver August", "Matthews", 4); @@ -393,11 +390,10 @@ public class SimpleMongoRepositoryTests { } @Test // DATAMONGO-2130 - @MongoVersion(asOf = "4.0") + @EnableIfReplicaSetAvailable + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void countShouldBePossibleInTransaction() { - assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - MongoTransactionManager txmgr = new MongoTransactionManager(template.getMongoDbFactory()); TransactionTemplate tt = new TransactionTemplate(txmgr); tt.afterPropertiesSet(); @@ -418,11 +414,10 @@ public class SimpleMongoRepositoryTests { } @Test // DATAMONGO-2130 - @MongoVersion(asOf = "4.0") + @EnableIfReplicaSetAvailable + @EnableIfMongoServerVersion(isGreaterThanEqual = "4.0") public void existsShouldBePossibleInTransaction() { - assumeThat(ReplicaSet.required().runsAsReplicaSet()).isTrue(); - MongoTransactionManager txmgr = new MongoTransactionManager(template.getMongoDbFactory()); TransactionTemplate tt = new TransactionTemplate(txmgr); tt.afterPropertiesSet(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java index 98bdc44f0..4d1fdea64 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleMongoRepositoryVersionedEntityTests.java @@ -20,6 +20,11 @@ import static org.assertj.core.api.Assumptions.*; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -64,6 +69,11 @@ public class SimpleMongoRepositoryVersionedEntityTests { protected String getDatabaseName() { return "database"; } + + @Override + protected Set> getInitialEntitySet() throws ClassNotFoundException { + return new HashSet<>(Arrays.asList(VersionedPerson.class)); + } } @Rule public MongoVersionRule mongoVersion = MongoVersionRule.any(); diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java index e727f6114..23b2405f9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/repository/support/SimpleReactiveMongoRepositoryVersionedEntityTests.java @@ -18,6 +18,9 @@ package org.springframework.data.mongodb.repository.support; import static org.springframework.data.mongodb.core.query.Criteria.*; import static org.springframework.data.mongodb.core.query.Query.*; +import java.util.Collections; +import java.util.Set; + import reactor.test.StepVerifier; import org.junit.Before; @@ -57,6 +60,11 @@ public class SimpleReactiveMongoRepositoryVersionedEntityTests { protected String getDatabaseName() { return "database"; } + + @Override + protected Set> getInitialEntitySet() { + return Collections.singleton(VersionedPerson.class); + } } @Autowired // diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java index 2da900ca0..b791fb1b9 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoClientExtension.java @@ -18,7 +18,6 @@ package org.springframework.data.mongodb.test.util; import static org.junit.platform.commons.util.AnnotationUtils.*; import static org.junit.platform.commons.util.ReflectionUtils.*; -import java.io.Closeable; import java.lang.reflect.Field; import java.util.function.Predicate; @@ -36,7 +35,6 @@ import org.junit.platform.commons.util.ExceptionUtils; import org.junit.platform.commons.util.ReflectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import org.springframework.util.ClassUtils; import com.mongodb.client.MongoClient; @@ -52,14 +50,17 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After private static final Logger LOGGER = LoggerFactory.getLogger(MongoClientExtension.class); - private static final Namespace NAMESPACE = Namespace.create(MongoClientExtension.class); - private static final String SYNC_KEY = "mongo.client.sync"; - private static final String REACTIVE_KEY = "mongo.client.reactive"; - private static final String SYNC_REPLSET_KEY = "mongo.client.replset.sync"; - private static final String REACTIVE_REPLSET_KEY = "mongo.client.replset.reactive"; + private static final Namespace NAMESPACE = MongoExtensions.Client.NAMESPACE; + + private static final String SYNC_KEY = MongoExtensions.Client.SYNC_KEY; + private static final String REACTIVE_KEY = MongoExtensions.Client.REACTIVE_KEY; + private static final String SYNC_REPLSET_KEY = MongoExtensions.Client.SYNC_REPLSET_KEY; + private static final String REACTIVE_REPLSET_KEY = MongoExtensions.Client.REACTIVE_REPLSET_KEY; @Override - public void afterAll(ExtensionContext extensionContext) throws Exception {} + public void afterAll(ExtensionContext extensionContext) throws Exception { + + } @Override public void beforeAll(ExtensionContext context) throws Exception { @@ -87,7 +88,7 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After }); } - private Object getMongoClient(Class type, ExtensionContext extensionContext, boolean replSet) { + protected Object getMongoClient(Class type, ExtensionContext extensionContext, boolean replSet) { Store store = extensionContext.getStore(NAMESPACE); @@ -120,6 +121,12 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After return new SyncClientHolder(replSet ? MongoTestUtils.replSetClient() : MongoTestUtils.client()); } + protected boolean holdsReplSetClient(ExtensionContext context) { + + Store store = context.getStore(NAMESPACE); + return store.get(SYNC_REPLSET_KEY) != null || store.get(REACTIVE_REPLSET_KEY) != null; + } + private void assertValidFieldCandidate(Field field) { assertSupportedType("field", field.getType()); @@ -137,14 +144,6 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After } } - private void closeClient(Store store, String key) { - - Closeable client = store.remove(key, Closeable.class); - if (client != null) { - - } - } - @Override public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) throws ParameterResolutionException { @@ -164,7 +163,7 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After final MongoClient client; - public SyncClientHolder(MongoClient client) { + SyncClientHolder(MongoClient client) { this.client = client; } @@ -182,7 +181,7 @@ public class MongoClientExtension implements Extension, BeforeAllCallback, After final com.mongodb.reactivestreams.client.MongoClient client; - public ReactiveClientHolder(com.mongodb.reactivestreams.client.MongoClient client) { + ReactiveClientHolder(com.mongodb.reactivestreams.client.MongoClient client) { this.client = client; } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java new file mode 100644 index 000000000..5f45cef1a --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoExtensions.java @@ -0,0 +1,41 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.test.util; + +import org.junit.jupiter.api.extension.ExtensionContext.Namespace; + +/** + * @author Christoph Strobl + */ +class MongoExtensions { + + static class Client { + + static final Namespace NAMESPACE = Namespace.create(MongoClientExtension.class); + static final String SYNC_KEY = "mongo.client.sync"; + static final String REACTIVE_KEY = "mongo.client.reactive"; + static final String SYNC_REPLSET_KEY = "mongo.client.replset.sync"; + static final String REACTIVE_REPLSET_KEY = "mongo.client.replset.reactive"; + } + + static class Termplate { + + static final Namespace NAMESPACE = Namespace.create(MongoTemplateExtension.class); + static final String SYNC = "mongo.template.sync"; + static final String REACTIVE = "mongo.template.reactive"; + } + +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java new file mode 100644 index 000000000..c88425ba8 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTemplateExtension.java @@ -0,0 +1,147 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.test.util; + +import static org.junit.platform.commons.util.AnnotationUtils.*; +import static org.junit.platform.commons.util.ReflectionUtils.*; + +import java.lang.reflect.Field; +import java.util.List; +import java.util.function.Predicate; + +import org.junit.jupiter.api.extension.ExtensionConfigurationException; +import org.junit.jupiter.api.extension.ExtensionContext; +import org.junit.jupiter.api.extension.ExtensionContext.Store; +import org.junit.jupiter.api.extension.ParameterContext; +import org.junit.jupiter.api.extension.ParameterResolutionException; +import org.junit.platform.commons.util.ExceptionUtils; +import org.junit.platform.commons.util.ReflectionUtils; +import org.junit.platform.commons.util.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.data.mapping.model.CamelCaseSplittingFieldNamingStrategy; +import org.springframework.data.mongodb.test.util.MongoExtensions.Termplate; +import org.springframework.data.util.ParsingUtils; +import org.springframework.util.ClassUtils; + +/** + * @author Christoph Strobl + */ +public class MongoTemplateExtension extends MongoClientExtension { + + private static final Logger LOGGER = LoggerFactory.getLogger(MongoTemplateExtension.class); + CamelCaseSplittingFieldNamingStrategy splitter = new CamelCaseSplittingFieldNamingStrategy("-"); + + @Override + public void afterAll(ExtensionContext context) throws Exception { + + } + + @Override + public void beforeAll(ExtensionContext context) throws Exception { + super.beforeAll(context); + + injectFields(context, null, ReflectionUtils::isStatic); + } + + private void injectFields(ExtensionContext context, Object testInstance, Predicate predicate) { + + findAnnotatedFields(context.getRequiredTestClass(), Template.class, predicate).forEach(field -> { + assertValidFieldCandidate(field); + try { + + makeAccessible(field).set(testInstance, + getMongoTemplate(field.getType(), field.getAnnotation(Template.class), context)); + } catch (Throwable t) { + ExceptionUtils.throwAsUncheckedException(t); + } + }); + } + + private void assertValidFieldCandidate(Field field) { + + assertSupportedType("field", field.getType()); + if (isPrivate(field)) { + throw new ExtensionConfigurationException("@MongoClient field [" + field + "] must not be private."); + } + } + + private void assertSupportedType(String target, Class type) { + + if (!ClassUtils.isAssignable(org.springframework.data.mongodb.core.MongoOperations.class, type) + && !ClassUtils.isAssignable(org.springframework.data.mongodb.core.ReactiveMongoOperations.class, type)) { + throw new ExtensionConfigurationException("Can only resolve @MongoClient " + target + " of type " + + org.springframework.data.mongodb.core.MongoOperations.class.getName() + " or " + + org.springframework.data.mongodb.core.ReactiveMongoOperations.class.getName() + " but was: " + + type.getName()); + } + } + + private Object getMongoTemplate(Class type, Template options, ExtensionContext extensionContext) { + + Store templateStore = extensionContext.getStore(MongoExtensions.Termplate.NAMESPACE); + + boolean replSetClient = holdsReplSetClient(extensionContext) || options.replicaSet(); + + String dbName = StringUtils.isNotBlank(options.database()) ? options.database() + : extensionContext.getTestClass().map(it -> { + List target = ParsingUtils.splitCamelCaseToLower(it.getSimpleName()); + return org.springframework.util.StringUtils.collectionToDelimitedString(target, "-"); + }).orElse("database"); + + if (ClassUtils.isAssignable(org.springframework.data.mongodb.core.MongoOperations.class, type)) { + + String key = Termplate.SYNC + "-" + dbName; + return templateStore.getOrComputeIfAbsent(key, it -> { + + com.mongodb.client.MongoClient client = (com.mongodb.client.MongoClient) getMongoClient( + com.mongodb.client.MongoClient.class, extensionContext, replSetClient); + return new MongoTestTemplate(client, dbName, options.initialEntitySet()); + }); + } + + if (ClassUtils.isAssignable(org.springframework.data.mongodb.core.ReactiveMongoOperations.class, type)) { + + String key = Termplate.REACTIVE + "-" + dbName; + return templateStore.getOrComputeIfAbsent(key, it -> { + + com.mongodb.reactivestreams.client.MongoClient client = (com.mongodb.reactivestreams.client.MongoClient) getMongoClient( + com.mongodb.reactivestreams.client.MongoClient.class, extensionContext, replSetClient); + return new ReactiveMongoTestTemplate(client, dbName, options.initialEntitySet()); + }); + } + + throw new IllegalStateException("Damn - something went wrong."); + } + + @Override + public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + return super.supportsParameter(parameterContext, extensionContext) || parameterContext.isAnnotated(Template.class); + } + + @Override + public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) + throws ParameterResolutionException { + + if (parameterContext.getParameter().getAnnotation(Template.class) == null) { + return super.resolveParameter(parameterContext, extensionContext); + } + Class parameterType = parameterContext.getParameter().getType(); + return getMongoTemplate(parameterType, parameterContext.getParameter().getAnnotation(Template.class), + extensionContext); + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java new file mode 100644 index 000000000..bf14555ea --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplate.java @@ -0,0 +1,144 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.test.util; + +import java.util.Arrays; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.bson.Document; +import org.springframework.context.ApplicationContext; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.mongodb.core.MongoTemplate; + +import com.mongodb.MongoWriteException; +import com.mongodb.client.MongoClient; +import com.mongodb.client.MongoCollection; + +/** + * A {@link MongoTemplate} with configuration hooks and extension suitable for tests. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class MongoTestTemplate extends MongoTemplate { + + private final MongoTestTemplateConfiguration cfg; + + public MongoTestTemplate(MongoClient client, String database, Class... initialEntities) { + this(cfg -> { + cfg.configureDatabaseFactory(it -> { + + it.client(client); + it.defaultDb(database); + }); + + cfg.configureMappingContext(it -> { + + it.autocreateIndex(false); + it.intitalEntitySet(initialEntities); + }); + }); + } + + public MongoTestTemplate(Consumer cfg) { + + this(new Supplier() { + @Override + public MongoTestTemplateConfiguration get() { + + MongoTestTemplateConfiguration config = new MongoTestTemplateConfiguration(); + cfg.accept(config); + return config; + } + }); + } + + public MongoTestTemplate(Supplier config) { + this(config.get()); + } + + public MongoTestTemplate(MongoTestTemplateConfiguration config) { + super(config.databaseFactory(), config.mongoConverter()); + + ApplicationContext applicationContext = config.getApplicationContext(); + if (applicationContext != null) { + setApplicationContext(applicationContext); + } + + this.cfg = config; + } + + public void flush() { + flush(PersistentEntities.of(getConverter().getMappingContext()).stream().map(it -> getCollectionName(it.getType())) + .collect(Collectors.toList())); + } + + public void flushDatabase() { + flush(getDb().listCollectionNames()); + } + + public void flush(Iterable collections) { + + for (String collection : collections) { + MongoCollection mongoCollection = getCollection(collection); + try { + mongoCollection.deleteMany(new Document()); + } catch (MongoWriteException e) { + mongoCollection.drop(); + } + } + } + + public void flush(Class... entities) { + flush(Arrays.asList(entities).stream().map(this::getCollectionName).collect(Collectors.toList())); + } + + public void flush(String... collections) { + flush(Arrays.asList(collections)); + } + + public void flush(Object... objects) { + + flush(Arrays.asList(objects).stream().map(it -> { + + if (it instanceof String) { + return (String) it; + } + if (it instanceof Class) { + return getCollectionName((Class) it); + } + return it.toString(); + }).collect(Collectors.toList())); + } + + public void dropDatabase() { + getDb().drop(); + } + + public void dropIndexes(String... collections) { + for (String collection : collections) { + getCollection(collection).dropIndexes(); + } + } + + public void dropIndexes(Class... entities) { + for (Class entity : entities) { + getCollection(getCollectionName(entity)).dropIndexes(); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java new file mode 100644 index 000000000..a3870957e --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestTemplateConfiguration.java @@ -0,0 +1,285 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.test.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.auditing.IsNewAwareAuditingHandler; +import org.springframework.data.convert.CustomConversions; +import org.springframework.data.mapping.context.MappingContext; +import org.springframework.data.mongodb.MongoDatabaseFactory; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.SimpleMongoClientDatabaseFactory; +import org.springframework.data.mongodb.core.SimpleReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.convert.DefaultDbRefResolver; +import org.springframework.data.mongodb.core.convert.MappingMongoConverter; +import org.springframework.data.mongodb.core.convert.MongoConverter; +import org.springframework.data.mongodb.core.convert.MongoCustomConversions; +import org.springframework.data.mongodb.core.mapping.MongoMappingContext; +import org.springframework.data.mongodb.core.mapping.event.AuditingEventListener; +import org.springframework.data.mongodb.core.mapping.event.MongoMappingEvent; +import org.springframework.lang.Nullable; + +/** + * @author Christoph Strobl + * @since 3.0 + */ +public class MongoTestTemplateConfiguration { + + private final DatabaseFactoryConfigurer dbFactoryConfig = new DatabaseFactoryConfigurer(); + private final MappingContextConfigurer mappingContextConfigurer = new MappingContextConfigurer(); + private final MongoConverterConfigurer mongoConverterConfigurer = new MongoConverterConfigurer(); + private final AuditingConfigurer auditingConfigurer = new AuditingConfigurer(); + private final ApplicationContextConfigurer applicationContextConfigurer = new ApplicationContextConfigurer(); + + private MongoMappingContext mappingContext; + private MappingMongoConverter converter; + private ApplicationContext context; + + private com.mongodb.client.MongoClient syncClient; + private com.mongodb.reactivestreams.client.MongoClient reactiveClient; + private MongoDatabaseFactory syncFactory; + private SimpleReactiveMongoDatabaseFactory reactiveFactory; + + MongoConverter mongoConverter() { + + if (converter == null) { + + converter = new MappingMongoConverter(new DefaultDbRefResolver(databaseFactory()), mappingContext()); + + if (mongoConverterConfigurer.customConversions != null) { + converter.setCustomConversions(mongoConverterConfigurer.customConversions); + } + converter.afterPropertiesSet(); + } + + return converter; + } + + List> getApplicationEventListener() { + + ArrayList> listeners = new ArrayList<>(applicationContextConfigurer.listeners); + if (auditingConfigurer.hasAuditingHandler()) { + listeners.add(new AuditingEventListener(() -> auditingConfigurer.auditingHandlers(mappingContext()))); + } + return listeners; + } + + @Nullable + ApplicationContext getApplicationContext() { + + if (applicationContextConfigurer.applicationContext == null) { + return null; + } + + if (context != null) { + return context; + } + + context = applicationContextConfigurer.applicationContext; + + if (context instanceof ConfigurableApplicationContext) { + + ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) this.context; + getApplicationEventListener().forEach(configurableApplicationContext::addApplicationListener); + + configurableApplicationContext.refresh(); + } + return context; + } + + MongoMappingContext mappingContext() { + + if (mappingContext == null) { + + mappingContext = new MongoMappingContext(); + mappingContext.setInitialEntitySet(mappingContextConfigurer.initialEntitySet()); + mappingContext.setAutoIndexCreation(mappingContextConfigurer.autocreateIndex); + mappingContext.afterPropertiesSet(); + } + + return mappingContext; + } + + MongoDatabaseFactory databaseFactory() { + + if (syncFactory == null) { + syncFactory = new SimpleMongoClientDatabaseFactory(syncClient(), defaultDatabase()); + } + + return syncFactory; + } + + ReactiveMongoDatabaseFactory reactiveDatabaseFactory() { + + if (reactiveFactory == null) { + reactiveFactory = new SimpleReactiveMongoDatabaseFactory(reactiveClient(), defaultDatabase()); + } + + return reactiveFactory; + } + + public MongoTestTemplateConfiguration configureDatabaseFactory(Consumer dbFactory) { + + dbFactory.accept(dbFactoryConfig); + return this; + } + + public MongoTestTemplateConfiguration configureMappingContext( + Consumer mappingContextConfigurerConsumer) { + mappingContextConfigurerConsumer.accept(mappingContextConfigurer); + return this; + } + + public MongoTestTemplateConfiguration configureApplicationContext( + Consumer applicationContextConfigurerConsumer) { + + applicationContextConfigurerConsumer.accept(applicationContextConfigurer); + return this; + } + + public MongoTestTemplateConfiguration configureAuditing(Consumer auditingConfigurerConsumer) { + + auditingConfigurerConsumer.accept(auditingConfigurer); + return this; + } + + public MongoTestTemplateConfiguration configureConversion( + Consumer mongoConverterConfigurerConsumer) { + + mongoConverterConfigurerConsumer.accept(mongoConverterConfigurer); + return this; + } + + com.mongodb.client.MongoClient syncClient() { + + if (syncClient == null) { + syncClient = dbFactoryConfig.syncClient != null ? dbFactoryConfig.syncClient : MongoTestUtils.client(); + } + + return syncClient; + } + + com.mongodb.reactivestreams.client.MongoClient reactiveClient() { + + if (reactiveClient == null) { + reactiveClient = dbFactoryConfig.reactiveClient != null ? dbFactoryConfig.reactiveClient + : MongoTestUtils.reactiveClient(); + } + + return reactiveClient; + } + + String defaultDatabase() { + return dbFactoryConfig.defaultDatabase != null ? dbFactoryConfig.defaultDatabase : "test"; + } + + public static class DatabaseFactoryConfigurer { + + com.mongodb.client.MongoClient syncClient; + com.mongodb.reactivestreams.client.MongoClient reactiveClient; + String defaultDatabase; + + public void client(com.mongodb.client.MongoClient client) { + this.syncClient = client; + } + + public void client(com.mongodb.reactivestreams.client.MongoClient client) { + this.reactiveClient = client; + } + + public void defaultDb(String defaultDatabase) { + this.defaultDatabase = defaultDatabase; + } + } + + public static class MongoConverterConfigurer { + + CustomConversions customConversions; + + public void customConversions(CustomConversions customConversions) { + this.customConversions = customConversions; + } + + public void customConverters(Converter... converters) { + customConversions(new MongoCustomConversions(Arrays.asList(converters))); + } + } + + public static class MappingContextConfigurer { + + Set> intitalEntitySet; + boolean autocreateIndex = false; + + public void autocreateIndex(boolean autocreateIndex) { + this.autocreateIndex = autocreateIndex; + } + + public void intitalEntitySet(Set> intitalEntitySet) { + this.intitalEntitySet = intitalEntitySet; + } + + public void intitalEntitySet(Class... initialEntitySet) { + this.intitalEntitySet = new HashSet<>(Arrays.asList(initialEntitySet)); + } + + Set> initialEntitySet() { + return intitalEntitySet != null ? intitalEntitySet : Collections.emptySet(); + } + } + + public static class AuditingConfigurer { + + Function auditingHandlerFunction; + + public void auditingHandler(Function auditingHandlerFunction) { + this.auditingHandlerFunction = auditingHandlerFunction; + } + + IsNewAwareAuditingHandler auditingHandlers(MongoMappingContext mongoMappingContext) { + return auditingHandlerFunction.apply(mongoMappingContext); + } + + boolean hasAuditingHandler() { + return auditingHandlerFunction != null; + } + } + + public static class ApplicationContextConfigurer { + + List>> listeners = new ArrayList<>(); + ApplicationContext applicationContext; + + public void applicationContext(ApplicationContext context) { + this.applicationContext = context; + } + + public void addEventListener(ApplicationListener> listener) { + this.listeners.add(listener); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java index 77361606d..1e0e34261 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/MongoTestUtils.java @@ -47,9 +47,9 @@ public class MongoTestUtils { private static final Environment ENV = new StandardEnvironment(); private static final Duration DEFAULT_TIMEOUT = Duration.ofMillis(10); - public static final String CONNECTION_STRING = "mongodb://127.0.0.1:27017/?replicaSet=rs0&w=majority"; + public static final String CONNECTION_STRING = "mongodb://127.0.0.1:27017/?replicaSet=rs0&w=majority&uuidrepresentation=javaLegacy"; - private static final String CONNECTION_STRING_PATTERN = "mongodb://%s:%s/?w=majority"; + private static final String CONNECTION_STRING_PATTERN = "mongodb://%s:%s/?w=majority&uuidrepresentation=javaLegacy"; private static final Version ANY = new Version(9999, 9999, 9999); @@ -185,6 +185,15 @@ public class MongoTestUtils { .verifyComplete(); } + public static void flushCollection(String dbName, String collectionName, + com.mongodb.client.MongoClient client) { + + com.mongodb.client.MongoDatabase database = client.getDatabase(dbName) + .withWriteConcern(WriteConcern.MAJORITY).withReadPreference(ReadPreference.primary()); + + database.getCollection(collectionName).deleteMany(new Document()); + } + /** * Create a new {@link com.mongodb.client.MongoClient} with defaults suitable for replica set usage. * diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java new file mode 100644 index 000000000..66762b533 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/ReactiveMongoTestTemplate.java @@ -0,0 +1,145 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.test.util; + +import com.mongodb.reactivestreams.client.MongoClient; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + +import java.util.Arrays; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.bson.Document; +import org.reactivestreams.Publisher; +import org.springframework.context.ApplicationContext; +import org.springframework.data.mapping.context.PersistentEntities; +import org.springframework.data.mongodb.ReactiveMongoDatabaseFactory; +import org.springframework.data.mongodb.core.ReactiveMongoTemplate; + +/** + * A {@link ReactiveMongoTemplate} with configuration hooks and extension suitable for tests. + * + * @author Christoph Strobl + * @since 3.0 + */ +public class ReactiveMongoTestTemplate extends ReactiveMongoTemplate { + + private final MongoTestTemplateConfiguration cfg; + + public ReactiveMongoTestTemplate(MongoClient client, String database, Class... initialEntities) { + this(cfg -> { + cfg.configureDatabaseFactory(it -> { + + it.client(client); + it.defaultDb(database); + }); + + cfg.configureMappingContext(it -> { + + it.autocreateIndex(false); + it.intitalEntitySet(initialEntities); + }); + }); + } + + public ReactiveMongoTestTemplate(Consumer cfg) { + + this(new Supplier() { + @Override + public MongoTestTemplateConfiguration get() { + + MongoTestTemplateConfiguration config = new MongoTestTemplateConfiguration(); + cfg.accept(config); + return config; + } + }); + } + + public ReactiveMongoTestTemplate(Supplier config) { + this(config.get()); + } + + public ReactiveMongoTestTemplate(MongoTestTemplateConfiguration config) { + super(config.reactiveDatabaseFactory(), config.mongoConverter()); + + ApplicationContext applicationContext = config.getApplicationContext(); + if (applicationContext != null) { + setApplicationContext(applicationContext); + } + + this.cfg = config; + } + + public ReactiveMongoDatabaseFactory getDatabaseFactory() { + return cfg.reactiveDatabaseFactory(); + } + + public Mono flush() { + return flush(Flux.fromStream( + PersistentEntities.of(getConverter().getMappingContext()).stream().map(it -> getCollectionName(it.getType())))); + } + + public Mono flushDatabase() { + return flush(getMongoDatabase().listCollectionNames()); + } + + public Mono flush(Class... entities) { + return flush(Flux.fromStream(Arrays.asList(entities).stream().map(this::getCollectionName))); + } + + public Mono flush(String... collections) { + return flush(Flux.fromArray(collections)); + } + + public Mono flush(Publisher collectionNames) { + + return Flux.from(collectionNames) + .flatMap(collection -> Mono.from(getCollection(collection).deleteMany(new Document())).then() + .onErrorResume(it -> Mono.from(getCollection(collection).drop()).then())) + .then(); + } + + public Mono flush(Object... objects) { + + return flush(Flux.fromStream(Arrays.asList(objects).stream().map(it -> { + + if (it instanceof String) { + return (String) it; + } + if (it instanceof Class) { + return getCollectionName((Class) it); + } + return it.toString(); + }))); + } + + public Mono dropDatabase() { + return Mono.from(getMongoDatabase().drop()).then(); + } + + public void dropIndexes(String... collections) { + for (String collection : collections) { + getCollection(collection).dropIndexes(); + } + } + + public void dropIndexes(Class... entities) { + for (Class entity : entities) { + getCollection(getCollectionName(entity)).dropIndexes(); + } + } +} diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java new file mode 100644 index 000000000..89e8f0227 --- /dev/null +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/test/util/Template.java @@ -0,0 +1,56 @@ +/* + * Copyright 2020 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.mongodb.test.util; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.extension.ExtensionContext; + +/** + * @author Christoph Strobl + * @since 3.0 + */ +@Target({ ElementType.FIELD, ElementType.PARAMETER }) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@ExtendWith(MongoTemplateExtension.class) +public @interface Template { + + /** + * @return name of the database to use. Use empty String to generate the database name for the + * {@link ExtensionContext#getTestClass() test class}. + */ + String database() default ""; + + /** + * Pre initilaize the {@link org.springframework.data.mapping.context.MappingContext} with the given entities. + * + * @return empty by default. + */ + Class[] initialEntitySet() default {}; + + /** + * Use a {@link ReplSetClient} if {@literal true}. + * + * @return false by default. + */ + boolean replicaSet() default false; +}