Compare commits
3 Commits
issue/4306
...
issue/arch
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
171f6641c7 | ||
|
|
4f8c29f48a | ||
|
|
e3ef84a56c |
2
pom.xml
2
pom.xml
@@ -5,7 +5,7 @@
|
||||
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.1.0-SNAPSHOT</version>
|
||||
<version>4.1.0-archunit-dependency-tests-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Spring Data MongoDB</name>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.1.0-SNAPSHOT</version>
|
||||
<version>4.1.0-archunit-dependency-tests-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.1.0-SNAPSHOT</version>
|
||||
<version>4.1.0-archunit-dependency-tests-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<parent>
|
||||
<groupId>org.springframework.data</groupId>
|
||||
<artifactId>spring-data-mongodb-parent</artifactId>
|
||||
<version>4.1.0-SNAPSHOT</version>
|
||||
<version>4.1.0-archunit-dependency-tests-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
<java-module-name>spring.data.mongodb</java-module-name>
|
||||
<project.root>${basedir}/..</project.root>
|
||||
<multithreadedtc>1.01</multithreadedtc>
|
||||
<archunit.version>1.0.1</archunit.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
@@ -250,9 +251,9 @@
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>de.schauderhaft.degraph</groupId>
|
||||
<artifactId>degraph-check</artifactId>
|
||||
<version>0.1.4</version>
|
||||
<groupId>com.tngtech.archunit</groupId>
|
||||
<artifactId>archunit</artifactId>
|
||||
<version>${archunit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -283,6 +283,10 @@ class EntityOperations {
|
||||
* @see EntityProjectionIntrospector#introspect(Class, Class)
|
||||
*/
|
||||
public <M, D> EntityProjection<M, D> introspectProjection(Class<M> resultType, Class<D> entityType) {
|
||||
|
||||
if (!queryMapper.getMappingContext().hasPersistentEntityFor(entityType)) {
|
||||
return (EntityProjection) EntityProjection.nonProjecting(resultType);
|
||||
}
|
||||
return introspector.introspect(resultType, entityType);
|
||||
}
|
||||
|
||||
|
||||
@@ -15,12 +15,16 @@
|
||||
*/
|
||||
package org.springframework.data.mongodb;
|
||||
|
||||
import static de.schauderhaft.degraph.check.JCheck.*;
|
||||
import static org.hamcrest.MatcherAssert.*;
|
||||
|
||||
import de.schauderhaft.degraph.configuration.NamedPattern;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import com.tngtech.archunit.base.DescribedPredicate;
|
||||
import com.tngtech.archunit.core.domain.JavaClass;
|
||||
import com.tngtech.archunit.core.domain.JavaClasses;
|
||||
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
||||
import com.tngtech.archunit.core.importer.ImportOption;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
import com.tngtech.archunit.library.dependencies.SliceAssignment;
|
||||
import com.tngtech.archunit.library.dependencies.SliceIdentifier;
|
||||
import com.tngtech.archunit.library.dependencies.SlicesRuleDefinition;
|
||||
import org.assertj.core.api.SoftAssertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
@@ -29,49 +33,138 @@ import org.junit.jupiter.api.Test;
|
||||
* @author Jens Schauder
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
@Disabled("Needs to be tansitioned to ArchUnit")
|
||||
class DependencyTests {
|
||||
|
||||
@Test
|
||||
void noInternalPackageCycles() {
|
||||
void cycleFree() {
|
||||
|
||||
assertThat(classpath() //
|
||||
.noJars() //
|
||||
.including("org.springframework.data.mongodb.**") //
|
||||
.filterClasspath("*target/classes") //
|
||||
.printOnFailure("degraph.graphml"), //
|
||||
violationFree() //
|
||||
);
|
||||
JavaClasses importedClasses = new ClassFileImporter() //
|
||||
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) //
|
||||
.withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_JARS) // we just analyze the code of this module.
|
||||
.importPackages("org.springframework.data.mongodb").that( //
|
||||
onlySpringData() //
|
||||
);
|
||||
|
||||
ArchRule rule = SlicesRuleDefinition.slices() //
|
||||
.matching("org.springframework.data.mongodb.(**)") //
|
||||
.should() //
|
||||
.beFreeOfCycles();
|
||||
|
||||
rule.check(importedClasses);
|
||||
}
|
||||
|
||||
@Test
|
||||
void onlyConfigMayUseRepository() {
|
||||
void acrossModules() {
|
||||
|
||||
assertThat(classpath() //
|
||||
.including("org.springframework.data.**") //
|
||||
.filterClasspath("*target/classes") //
|
||||
.printOnFailure("onlyConfigMayUseRepository.graphml") //
|
||||
.withSlicing("slices", //
|
||||
"**.(config).**", //
|
||||
new NamedPattern("**.cdi.**", "config"), //
|
||||
"**.(repository).**", //
|
||||
new NamedPattern("**", "other"))
|
||||
.allow("config", "repository", "other"), //
|
||||
violationFree() //
|
||||
);
|
||||
JavaClasses importedClasses = new ClassFileImporter().withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
|
||||
.importPackages( //
|
||||
"org.springframework.data.mongodb", // Spring Data Relational
|
||||
"org.springframework.data" // Spring Data Commons
|
||||
).that(onlySpringData());
|
||||
|
||||
ArchRule rule = SlicesRuleDefinition.slices() //
|
||||
.assignedFrom(subModuleSlicing()) //
|
||||
.should().beFreeOfCycles();
|
||||
|
||||
rule.check(importedClasses);
|
||||
}
|
||||
|
||||
@Test
|
||||
void commonsInternaly() {
|
||||
// GH-1058
|
||||
void testGetFirstPackagePart() {
|
||||
|
||||
assertThat(classpath() //
|
||||
.noJars() //
|
||||
.including("org.springframework.data.**") //
|
||||
.excluding("org.springframework.data.mongodb.**") //
|
||||
.filterClasspath("*target/classes") //
|
||||
.printTo("commons.graphml"), //
|
||||
violationFree() //
|
||||
);
|
||||
SoftAssertions.assertSoftly(softly -> {
|
||||
softly.assertThat(getFirstPackagePart("a.b.c")).isEqualTo("a");
|
||||
softly.assertThat(getFirstPackagePart("a")).isEqualTo("a");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
// GH-1058
|
||||
void testSubModule() {
|
||||
|
||||
SoftAssertions.assertSoftly(softly -> {
|
||||
softly.assertThat(subModule("a.b", "a.b.c.d")).isEqualTo("c");
|
||||
softly.assertThat(subModule("a.b", "a.b.c")).isEqualTo("c");
|
||||
softly.assertThat(subModule("a.b", "a.b")).isEqualTo("");
|
||||
});
|
||||
}
|
||||
|
||||
private DescribedPredicate<JavaClass> onlySpringData() {
|
||||
|
||||
return new DescribedPredicate<>("Spring Data Classes") {
|
||||
@Override
|
||||
public boolean test(JavaClass input) {
|
||||
return input.getPackageName().startsWith("org.springframework.data");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private DescribedPredicate<JavaClass> ignore(Class<?> type) {
|
||||
|
||||
return new DescribedPredicate<>("ignored class " + type.getName()) {
|
||||
@Override
|
||||
public boolean test(JavaClass input) {
|
||||
return !input.getFullName().startsWith(type.getName());
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private DescribedPredicate<JavaClass> ignorePackage(String type) {
|
||||
|
||||
return new DescribedPredicate<>("ignored class " + type) {
|
||||
@Override
|
||||
public boolean test(JavaClass input) {
|
||||
return !input.getPackageName().equals(type);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private String getFirstPackagePart(String subpackage) {
|
||||
|
||||
int index = subpackage.indexOf(".");
|
||||
if (index < 0) {
|
||||
return subpackage;
|
||||
}
|
||||
return subpackage.substring(0, index);
|
||||
}
|
||||
|
||||
private String subModule(String basePackage, String packageName) {
|
||||
|
||||
if (packageName.startsWith(basePackage) && packageName.length() > basePackage.length()) {
|
||||
|
||||
final int index = basePackage.length() + 1;
|
||||
String subpackage = packageName.substring(index);
|
||||
return getFirstPackagePart(subpackage);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private SliceAssignment subModuleSlicing() {
|
||||
return new SliceAssignment() {
|
||||
|
||||
@Override
|
||||
public SliceIdentifier getIdentifierOf(JavaClass javaClass) {
|
||||
|
||||
String packageName = javaClass.getPackageName();
|
||||
|
||||
String subModule = subModule("org.springframework.data.mongodb", packageName);
|
||||
if (!subModule.isEmpty()) {
|
||||
return SliceIdentifier.of(subModule);
|
||||
}
|
||||
|
||||
subModule = subModule("org.springframework.data", packageName);
|
||||
if (!subModule.isEmpty()) {
|
||||
return SliceIdentifier.of(subModule);
|
||||
}
|
||||
|
||||
return SliceIdentifier.ignore();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return "Submodule";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2526,6 +2526,26 @@ public class MongoTemplateTests {
|
||||
assertThat(projection.getName()).isEqualTo("Walter");
|
||||
}
|
||||
|
||||
@Test // GH-4300
|
||||
public void findAndReplaceShouldAllowNativeDomainTypesAndReturnAProjection() {
|
||||
|
||||
MyPerson person = new MyPerson("Walter");
|
||||
person.address = new Address("TX", "Austin");
|
||||
template.save(person);
|
||||
|
||||
MyPerson previous = template.findAndReplace(query(where("name").is("Walter")),
|
||||
new org.bson.Document("name", "Heisenberg"), FindAndReplaceOptions.options(), org.bson.Document.class,
|
||||
"myPerson", MyPerson.class);
|
||||
|
||||
assertThat(previous).isNotNull();
|
||||
assertThat(previous.getAddress()).isEqualTo(person.address);
|
||||
|
||||
org.bson.Document loaded = template.execute(MyPerson.class, collection -> {
|
||||
return collection.find(new org.bson.Document("name", "Heisenberg")).first();
|
||||
});
|
||||
assertThat(loaded.get("_id")).isEqualTo(new ObjectId(person.id));
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-407
|
||||
public void updatesShouldRetainTypeInformationEvenForCollections() {
|
||||
|
||||
|
||||
@@ -2392,6 +2392,17 @@ public class MongoTemplateUnitTests extends MongoOperationsUnitTests {
|
||||
.isEqualTo(new com.mongodb.client.model.TimeSeriesOptions("time_stamp").toString());
|
||||
}
|
||||
|
||||
@Test // GH-4300
|
||||
void findAndReplaceAllowsDocumentSourceType() {
|
||||
|
||||
template.findAndReplace(new Query(), new Document("spring", "data"), FindAndReplaceOptions.options().upsert(),
|
||||
Document.class, "coll-1", Person.class);
|
||||
|
||||
verify(db).getCollection(eq("coll-1"), eq(Document.class));
|
||||
verify(collection).findOneAndReplace((Bson) any(Bson.class), eq(new Document("spring", "data")),
|
||||
any(FindOneAndReplaceOptions.class));
|
||||
}
|
||||
|
||||
class AutogenerateableId {
|
||||
|
||||
@Id BigInteger id;
|
||||
|
||||
@@ -729,6 +729,32 @@ public class ReactiveMongoTemplateTests {
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // GH-4300
|
||||
public void findAndReplaceShouldAllowNativeDomainTypesAndReturnAProjection() {
|
||||
|
||||
MongoTemplateTests.MyPerson person = new MongoTemplateTests.MyPerson("Walter");
|
||||
person.address = new Address("TX", "Austin");
|
||||
template.save(person) //
|
||||
.as(StepVerifier::create) //
|
||||
.expectNextCount(1) //
|
||||
.verifyComplete();
|
||||
|
||||
template
|
||||
.findAndReplace(query(where("name").is("Walter")), new org.bson.Document("name", "Heisenberg"),
|
||||
FindAndReplaceOptions.options(), org.bson.Document.class, "myPerson", MongoTemplateTests.MyPerson.class)
|
||||
.as(StepVerifier::create) //
|
||||
.consumeNextWith(actual -> {
|
||||
assertThat(actual.getAddress()).isEqualTo(person.address);
|
||||
}).verifyComplete();
|
||||
|
||||
template.execute(MongoTemplateTests.MyPerson.class, collection -> {
|
||||
return collection.find(new org.bson.Document("name", "Heisenberg")).first();
|
||||
}).as(StepVerifier::create) //
|
||||
.consumeNextWith(loaded -> {
|
||||
assertThat(loaded.get("_id")).isEqualTo(new ObjectId(person.id));
|
||||
}).verifyComplete();
|
||||
}
|
||||
|
||||
@Test // DATAMONGO-1827
|
||||
void findAndReplaceShouldReplaceObjectReturingNew() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user