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.
This commit is contained in:
Christoph Strobl
2020-02-27 13:19:58 +01:00
committed by Mark Paluch
parent 96ffb0b7f4
commit 8029acb3fb
69 changed files with 1659 additions and 732 deletions

View File

@@ -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<T>
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<T>
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<T>
private @Nullable String databaseName;
private @Nullable String collectionName;
private @Nullable Duration maxAwaitTime;
private @Nullable MessageListener<ChangeStreamDocument<Document>, ? super T> listener;
private ChangeStreamOptionsBuilder delegate = ChangeStreamOptions.builder();
@@ -417,6 +444,20 @@ public class ChangeStreamRequest<T>
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<T> 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<T>
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()));
}
}
}

View File

@@ -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<ChangeStreamDocument<Document>,
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) {

View File

@@ -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<S, T, O extends RequestOptions> {
@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.
*

View File

@@ -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<Document, Object> {
iterable = iterable.collation(collation);
}
if (!options.maxAwaitTime().isZero()) {
iterable = iterable.maxAwaitTime(options.maxAwaitTime().toMillis(), TimeUnit.MILLISECONDS);
}
return iterable.iterator();
}
}

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}

View File

@@ -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<Class<?>> getInitialEntitySet() {
return Collections.singleton(Person.class);
}
}
@RequiredArgsConstructor

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
@Autowired MongoOperations operations;

View File

@@ -172,6 +172,7 @@ public class AbstractMongoConfigurationUnitTests {
public MongoTypeMapper typeMapper() {
return new CustomMongoTypeMapper();
}
}
static class ConfigurationWithMultipleBasePackages extends AbstractMongoClientConfiguration {

View File

@@ -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<AuditablePerson> auditorProvider() {
return mock(AuditorAware.class);
}
@Override
protected Set<Class<?>> 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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
static class VersionedAuditablePerson extends AuditablePerson {

View File

@@ -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<Class<?>> getInitialEntitySet() {
return new HashSet<>(
Arrays.asList(AuditablePerson.class, VersionedAuditablePerson.class, SimpleVersionedAuditablePerson.class));
}
@Bean
@SuppressWarnings("unchecked")
public AuditorAware<AuditablePerson> auditorProvider() {

View File

@@ -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");

View File

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

View File

@@ -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<org.bson.Document> collection;
@Template //
static MongoTestTemplate template;
@Before
MongoCollection<org.bson.Document> 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);

View File

@@ -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<Document> 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<Document> 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)));

View File

@@ -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"));

View File

@@ -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";

View File

@@ -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";

View File

@@ -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";

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
@Autowired MongoTemplate template;

View File

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

View File

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

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
@Autowired MongoTemplate template;

View File

@@ -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<org.bson.Document> collection(Class<?> type) {
return client.getDatabase(DB_NAME).getCollection(template.getCollectionName(type));
return template.getCollection(template.getCollectionName(type));
}
@Document("scores")

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
@Autowired MongoTemplate template;

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
@Autowired MongoOperations mongoOps;

View File

@@ -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";

View File

@@ -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<Class<?>> getInitialEntitySet() {
return Collections.emptySet();
}
}
@Autowired ReactiveMongoTemplate template;

View File

@@ -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<ChangeStreamEvent<Document>> 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<ChangeStreamEvent<Person>> 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<ChangeStreamEvent<Person>> 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<ChangeStreamEvent<Person>> 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<ChangeStreamEvent<Person>> documents = new LinkedBlockingQueue<>(100);
@@ -1586,7 +1581,6 @@ public class ReactiveMongoTemplateTests {
}
@Test // DATAMONGO-2189
@DirtiesContext
public void afterSaveEventContainsSavedObjectUsingInsert() {
AtomicReference<ImmutableVersioned> saved = createAfterSaveReference();
@@ -1602,7 +1596,6 @@ public class ReactiveMongoTemplateTests {
}
@Test // DATAMONGO-2189
@DirtiesContext
public void afterSaveEventContainsSavedObjectUsingInsertAll() {
AtomicReference<ImmutableVersioned> 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<ChangeStreamEvent<Person>> 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<ChangeStreamEvent<Person>> documents = new LinkedBlockingQueue<>(100);

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}

View File

@@ -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<Void>() {
@Override
public Void doInCollection(MongoCollection<Document> collection) throws MongoException, DataAccessException {
List<WriteModel<Document>> 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<Document> coll = mongoTemplate.getCollection(INPUT_COLLECTION);
@@ -332,7 +315,6 @@ public class AggregationTests {
}
@Test // DATAMONGO-1391
@MongoVersion(asOf = "3.2")
public void shouldUnwindPreserveEmpty() {
MongoCollection<Document> 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();

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return new HashSet<>(Arrays.asList(ImmutableAuditableEntityWithVersion.class, KAuditableVersionedEntity.class));
}
}
@Autowired MongoTemplate template;

View File

@@ -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<Class<?>> getInitialEntitySet() {
return Collections.emptySet();
}
}
@Autowired ReactiveMongoTemplate template;

View File

@@ -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);

View File

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

View File

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

View File

@@ -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<Class<?>> 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

View File

@@ -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<Class<?>> 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<Venue2DSphere> 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<VenueWithDistanceField> 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<VenueWithDistanceField> 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<Venue2DSphere> 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<Venue2DSphere> 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<Venue2DSphere> 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<Venue2DSphere> 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<Venue2DSphere> 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() {

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
@AfterEach

View File

@@ -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")));
}

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}

View File

@@ -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);

View File

@@ -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<XObject> results = mongoTemplate.group("group_test_collection", GroupBy.key("x")
GroupByResults<XObject> 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<XObject> 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<XObject> results = mongoTemplate.group("group_test_collection",
GroupByResults<XObject> 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<XObject> results = mongoTemplate.group(where("x").gt(0), "group_test_collection",
GroupByResults<XObject> 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<Document> c = mongoTemplate.getDb().getCollection("group_test_collection", Document.class);
MongoCollection<Document> c = mongoTemplate.getDb().getCollection(GROUP_TEST_COLLECTION, Document.class);
c.insertOne(new Document("x", 1));
c.insertOne(new Document("x", 1));

View File

@@ -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<ChangeStreamDocument<Document>, Document> messageListener = new CollectingMessageListener<>();
ChangeStreamRequest<Document> request = new ChangeStreamRequest<>(messageListener, () -> "user");
ChangeStreamRequest<Document> 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<User> 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<User> 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<User> 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<User> messageBodies = messageListener.getMessages().stream().map(Message::getBody)
.collect(Collectors.toList());
@@ -277,7 +285,9 @@ public class ChangeStreamTests {
public void resumesCorrectly() throws InterruptedException {
CollectingMessageListener<ChangeStreamDocument<Document>, 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<ChangeStreamDocument<Document>, User> messageListener2 = new CollectingMessageListener<>();
ChangeStreamRequest<User> 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<User> messageBodies = messageListener2.getMessages().stream().map(Message::getBody)
.collect(Collectors.toList());
@@ -309,7 +319,8 @@ public class ChangeStreamTests {
public void readsAndConvertsMessageBodyCorrectly() throws InterruptedException {
CollectingMessageListener<ChangeStreamDocument<Document>, User> messageListener = new CollectingMessageListener<>();
ChangeStreamRequest<User> request = new ChangeStreamRequest<>(messageListener, () -> "user");
ChangeStreamRequest<User> 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<ChangeStreamDocument<Document>, User> messageListener = new CollectingMessageListener<>();
ChangeStreamRequest<User> request = new ChangeStreamRequest<>(messageListener, () -> "user");
ChangeStreamRequest<User> 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<ChangeStreamDocument<Document>, Document> messageListener = new CollectingMessageListener<>();
ChangeStreamRequest<Document> request = new ChangeStreamRequest<>(messageListener, () -> "user");
ChangeStreamRequest<Document> 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<User> 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<Document> 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<ChangeStreamDocument<Document>, 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<User> messageBodies = messageListener2.getMessages().stream().map(Message::getBody)
.collect(Collectors.toList());
@@ -461,6 +479,7 @@ public class ChangeStreamTests {
ChangeStreamRequest<User> 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<User> 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);

View File

@@ -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<Document> collection;
MongoCollection<Document> collection2;
MongoDatabaseFactory dbFactory = template.getMongoDbFactory();
MongoCollection<Document> collection = template.getCollection(COLLECTION_NAME);
MongoCollection<Document> collection2 = template.getCollection(COLLECTION_2_NAME);
private CollectingMessageListener<Object, Object> 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<Document, Document> 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<ChangeStreamDocument<Document>, 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());
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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();

View File

@@ -69,6 +69,8 @@ public class MongoJsonSchemaTests {
protected String getDatabaseName() {
return "json-schema-tests";
}
}
@Autowired MongoTemplate template;

View File

@@ -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<Class<?>> getInitialEntitySet() {
return Collections.emptySet();
}
}
@Autowired ReactiveMongoTemplate template;

View File

@@ -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() {

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.emptySet();
}
}
@Autowired UserWithComplexIdRepository repo;

View File

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

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return Collections.singleton(Person.class);
}
}
@Autowired MongoClient client;

View File

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

View File

@@ -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 {}

View File

@@ -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 {}

View File

@@ -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 {}

View File

@@ -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<Class<?>> getInitialEntitySet() {
return Collections.singleton(Person.class);
}
}
@BeforeClass

View File

@@ -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<Person> all;
private MongoEntityInformation<Person, String> personEntityInformation = new CustomizedPersonInformation();
private SimpleMongoRepository<Person, String> repository;
private SimpleMongoRepository<Person, String> repository = new SimpleMongoRepository<>(personEntityInformation,
template);
@Before
@BeforeEach
public void setUp() {
repository = new SimpleMongoRepository<Person, String>(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();

View File

@@ -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<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
return new HashSet<>(Arrays.asList(VersionedPerson.class));
}
}
@Rule public MongoVersionRule mongoVersion = MongoVersionRule.any();

View File

@@ -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<Class<?>> getInitialEntitySet() {
return Collections.singleton(VersionedPerson.class);
}
}
@Autowired //

View File

@@ -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;
}

View File

@@ -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";
}
}

View File

@@ -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<Field> 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<String> 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);
}
}

View File

@@ -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<MongoTestTemplateConfiguration> cfg) {
this(new Supplier<MongoTestTemplateConfiguration>() {
@Override
public MongoTestTemplateConfiguration get() {
MongoTestTemplateConfiguration config = new MongoTestTemplateConfiguration();
cfg.accept(config);
return config;
}
});
}
public MongoTestTemplate(Supplier<MongoTestTemplateConfiguration> 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<String> collections) {
for (String collection : collections) {
MongoCollection<Document> 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();
}
}
}

View File

@@ -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<ApplicationListener<?>> getApplicationEventListener() {
ArrayList<ApplicationListener<?>> 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<DatabaseFactoryConfigurer> dbFactory) {
dbFactory.accept(dbFactoryConfig);
return this;
}
public MongoTestTemplateConfiguration configureMappingContext(
Consumer<MappingContextConfigurer> mappingContextConfigurerConsumer) {
mappingContextConfigurerConsumer.accept(mappingContextConfigurer);
return this;
}
public MongoTestTemplateConfiguration configureApplicationContext(
Consumer<ApplicationContextConfigurer> applicationContextConfigurerConsumer) {
applicationContextConfigurerConsumer.accept(applicationContextConfigurer);
return this;
}
public MongoTestTemplateConfiguration configureAuditing(Consumer<AuditingConfigurer> auditingConfigurerConsumer) {
auditingConfigurerConsumer.accept(auditingConfigurer);
return this;
}
public MongoTestTemplateConfiguration configureConversion(
Consumer<MongoConverterConfigurer> 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<Class<?>> intitalEntitySet;
boolean autocreateIndex = false;
public void autocreateIndex(boolean autocreateIndex) {
this.autocreateIndex = autocreateIndex;
}
public void intitalEntitySet(Set<Class<?>> intitalEntitySet) {
this.intitalEntitySet = intitalEntitySet;
}
public void intitalEntitySet(Class<?>... initialEntitySet) {
this.intitalEntitySet = new HashSet<>(Arrays.asList(initialEntitySet));
}
Set<Class<?>> initialEntitySet() {
return intitalEntitySet != null ? intitalEntitySet : Collections.emptySet();
}
}
public static class AuditingConfigurer {
Function<MappingContext, IsNewAwareAuditingHandler> auditingHandlerFunction;
public void auditingHandler(Function<MappingContext, IsNewAwareAuditingHandler> auditingHandlerFunction) {
this.auditingHandlerFunction = auditingHandlerFunction;
}
IsNewAwareAuditingHandler auditingHandlers(MongoMappingContext mongoMappingContext) {
return auditingHandlerFunction.apply(mongoMappingContext);
}
boolean hasAuditingHandler() {
return auditingHandlerFunction != null;
}
}
public static class ApplicationContextConfigurer {
List<ApplicationListener<MongoMappingEvent<?>>> listeners = new ArrayList<>();
ApplicationContext applicationContext;
public void applicationContext(ApplicationContext context) {
this.applicationContext = context;
}
public void addEventListener(ApplicationListener<MongoMappingEvent<?>> listener) {
this.listeners.add(listener);
}
}
}

View File

@@ -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.
*

View File

@@ -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<MongoTestTemplateConfiguration> cfg) {
this(new Supplier<MongoTestTemplateConfiguration>() {
@Override
public MongoTestTemplateConfiguration get() {
MongoTestTemplateConfiguration config = new MongoTestTemplateConfiguration();
cfg.accept(config);
return config;
}
});
}
public ReactiveMongoTestTemplate(Supplier<MongoTestTemplateConfiguration> 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<Void> flush() {
return flush(Flux.fromStream(
PersistentEntities.of(getConverter().getMappingContext()).stream().map(it -> getCollectionName(it.getType()))));
}
public Mono<Void> flushDatabase() {
return flush(getMongoDatabase().listCollectionNames());
}
public Mono<Void> flush(Class<?>... entities) {
return flush(Flux.fromStream(Arrays.asList(entities).stream().map(this::getCollectionName)));
}
public Mono<Void> flush(String... collections) {
return flush(Flux.fromArray(collections));
}
public Mono<Void> flush(Publisher<String> 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<Void> 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<Void> 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();
}
}
}

View File

@@ -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;
}