Skip to content

Simplify PreferredConstructorDiscovererUnitTests #2724

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.util.List;

import org.springframework.core.annotation.MergedAnnotations;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.annotation.PersistenceCreator;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;

Expand All @@ -34,6 +34,7 @@
* @author Mark Paluch
* @author Myeonghyeon Lee
* @author Xeno Amess
* @author Pavel Anisimov
*/
public final class PreferredConstructor<T, P extends PersistentProperty<P>> extends InstanceCreatorMetadataSupport<T, P> {

Expand Down Expand Up @@ -75,12 +76,12 @@ public boolean isNoArgConstructor() {
}

/**
* Returns whether the constructor was explicitly selected (by {@link PersistenceConstructor}).
* Returns whether the constructor was explicitly selected (by {@link PersistenceCreator}).
*
* @return
*/
public boolean isExplicitlyAnnotated() {
return MergedAnnotations.from(getExecutable()).isPresent(PersistenceConstructor.class);
return MergedAnnotations.from(getExecutable()).isPresent(PersistenceCreator.class);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.annotation.PersistenceConstructor;
import org.springframework.data.annotation.PersistenceCreator;
import org.springframework.data.mapping.PreferredConstructorDiscovererUnitTests.Outer.Inner;
import org.springframework.data.mapping.model.BasicPersistentEntity;
Expand All @@ -39,68 +38,68 @@
* @author Roman Rodov
* @author Mark Paluch
* @author Christoph Strobl
* @author Pavel Anisimov
*/
class PreferredConstructorDiscovererUnitTests<P extends PersistentProperty<P>> {

@Test // DATACMNS-1126
void findsNoArgConstructorForClassWithoutExplicitConstructor() {

assertThat(PreferredConstructorDiscoverer.discover(EntityWithoutConstructor.class)).satisfies(constructor -> {
var constructor = PreferredConstructorDiscoverer.discover(EntityWithoutConstructor.class);

assertThat(constructor).isNotNull();
assertThat(constructor.isNoArgConstructor()).isTrue();
assertThat(constructor.isExplicitlyAnnotated()).isFalse();
});
assertThat(constructor).isNotNull();
assertThat(constructor.isNoArgConstructor()).isTrue();
assertThat(constructor.isExplicitlyAnnotated()).isFalse();
}

@Test // DATACMNS-1126
void findsNoArgConstructorForClassWithMultipleConstructorsAndNoArgOne() {

assertThat(PreferredConstructorDiscoverer.discover(ClassWithEmptyConstructor.class)).satisfies(constructor -> {
var constructor = PreferredConstructorDiscoverer.discover(ClassWithEmptyConstructor.class);

assertThat(constructor).isNotNull();
assertThat(constructor.isNoArgConstructor()).isTrue();
assertThat(constructor.isExplicitlyAnnotated()).isFalse();
});
assertThat(constructor).isNotNull();
assertThat(constructor.isNoArgConstructor()).isTrue();
assertThat(constructor.isExplicitlyAnnotated()).isFalse();
}

@Test // DATACMNS-1126
void doesNotThrowExceptionForMultipleConstructorsAndNoNoArgConstructorWithoutAnnotation() {

assertThat(PreferredConstructorDiscoverer.discover(ClassWithMultipleConstructorsWithoutEmptyOne.class)).isNull();
var constructor = PreferredConstructorDiscoverer.discover(ClassWithMultipleConstructorsWithoutEmptyOne.class);

assertThat(constructor).isNull();
}

@Test // DATACMNS-1126
@SuppressWarnings({ "unchecked", "rawtypes" })
void usesConstructorWithAnnotationOverEveryOther() {

assertThat(PreferredConstructorDiscoverer.discover(ClassWithMultipleConstructorsAndAnnotation.class))
.satisfies(constructor -> {
PreferredConstructor<ClassWithMultipleConstructorsAndAnnotation, P> constructor =
PreferredConstructorDiscoverer.discover(ClassWithMultipleConstructorsAndAnnotation.class);

assertThat(constructor).isNotNull();
assertThat(constructor.isNoArgConstructor()).isFalse();
assertThat(constructor.isExplicitlyAnnotated()).isTrue();
assertThat(constructor).isNotNull();
assertThat(constructor.isNoArgConstructor()).isFalse();
assertThat(constructor.isExplicitlyAnnotated()).isTrue();

assertThat(constructor.hasParameters()).isTrue();
assertThat(constructor.hasParameters()).isTrue();

Iterator<Parameter<Object, P>> parameters = (Iterator) constructor.getParameters().iterator();
Iterator<Parameter<Object, P>> parameters = constructor.getParameters().iterator();

Parameter<?, P> parameter = parameters.next();
assertThat(parameter.getType().getType()).isEqualTo(Long.class);
assertThat(parameters.hasNext()).isFalse();
});
Parameter<?, P> parameter = parameters.next();
assertThat(parameter.getType().getType()).isEqualTo(Long.class);
assertThat(parameters.hasNext()).isFalse();
}

@Test // DATACMNS-134, DATACMNS-1126
void discoversInnerClassConstructorCorrectly() {

PersistentEntity<Inner, P> entity = new BasicPersistentEntity<>(TypeInformation.of(Inner.class));

assertThat(PreferredConstructorDiscoverer.discover(entity)).satisfies(constructor -> {
var constructor = PreferredConstructorDiscoverer.discover(entity);

assertThat(constructor).isNotNull();

Parameter<?, P> parameter = constructor.getParameters().iterator().next();
assertThat(constructor.isParentParameter(parameter)).isTrue();
});
Parameter<?, P> parameter = constructor.getParameters().iterator().next();
assertThat(constructor.isParentParameter(parameter)).isTrue();
}

@Test // DATACMNS-1082, DATACMNS-1126
Expand All @@ -109,77 +108,80 @@ void skipsSyntheticConstructor() {
PersistentEntity<SyntheticConstructor, P> entity = new BasicPersistentEntity<>(
TypeInformation.of(SyntheticConstructor.class));

assertThat(PreferredConstructorDiscoverer.discover(entity)).satisfies(constructor -> {
var constructor = PreferredConstructorDiscoverer.discover(entity);
assertThat(constructor).isNotNull();

var annotation = constructor.getConstructor().getAnnotation(PersistenceConstructor.class);
assertThat(annotation).isNotNull();
assertThat(constructor.getConstructor().isSynthetic()).isFalse();
});
var annotation = constructor.getConstructor().getAnnotation(PersistenceCreator.class);
assertThat(annotation).isNotNull();
assertThat(constructor.getConstructor().isSynthetic()).isFalse();
}

@Test // GH-2313
void capturesEnclosingTypeParameterOfNonStaticInnerClass() {

assertThat(PreferredConstructorDiscoverer.discover(NonStaticWithGenericTypeArgUsedInCtor.class)).satisfies(ctor -> {
var constructor = PreferredConstructorDiscoverer.discover(NonStaticWithGenericTypeArgUsedInCtor.class);

assertThat(ctor.getParameters()).hasSize(2);
assertThat(ctor.getParameters().get(0).getName()).isEqualTo("this$0");
assertThat(ctor.getParameters().get(1).getName()).isEqualTo("value");
});
assertThat(constructor).isNotNull();
assertThat(constructor.getParameters()).hasSize(2);
assertThat(constructor.getParameters().get(0).getName()).isEqualTo("this$0");
assertThat(constructor.getParameters().get(1).getName()).isEqualTo("value");
}

@Test // GH-2313
void capturesSuperClassEnclosingTypeParameterOfNonStaticInnerClass() {

assertThat(PreferredConstructorDiscoverer.discover(NonStaticInnerWithGenericArgUsedInCtor.class))
.satisfies(ctor -> {
var constructor = PreferredConstructorDiscoverer.discover(NonStaticInnerWithGenericArgUsedInCtor.class);

assertThat(ctor.getParameters()).hasSize(2);
assertThat(ctor.getParameters().get(0).getName()).isEqualTo("this$0");
assertThat(ctor.getParameters().get(1).getName()).isEqualTo("value");
});
assertThat(constructor).isNotNull();
assertThat(constructor.getParameters()).hasSize(2);
assertThat(constructor.getParameters().get(0).getName()).isEqualTo("this$0");
assertThat(constructor.getParameters().get(1).getName()).isEqualTo("value");
}

@Test // GH-2332
void detectsMetaAnnotatedValueAnnotation() {

assertThat(PreferredConstructorDiscoverer.discover(ClassWithMetaAnnotatedParameter.class)).satisfies(ctor -> {
var constructor = PreferredConstructorDiscoverer.discover(ClassWithMetaAnnotatedParameter.class);

assertThat(ctor.getParameters().get(0).getSpelExpression()).isEqualTo("${hello-world}");
assertThat(ctor.getParameters().get(0).getAnnotations()).isNotNull();
});
assertThat(constructor).isNotNull();
assertThat(constructor.getParameters().get(0).getSpelExpression()).isEqualTo("${hello-world}");
assertThat(constructor.getParameters().get(0).getAnnotations()).isNotNull();
}

@Test // GH-2332
void detectsCanonicalRecordConstructor() {
void detectsCanonicalRecordConstructorWhenRecordHasSingleArgConstructor() {

assertThat(PreferredConstructorDiscoverer.discover(RecordWithSingleArgConstructor.class)).satisfies(ctor -> {
var constructor = PreferredConstructorDiscoverer.discover(RecordWithSingleArgConstructor.class);

assertThat(ctor.getParameters()).hasSize(2);
assertThat(ctor.getParameters().get(0).getRawType()).isEqualTo(Long.class);
assertThat(ctor.getParameters().get(1).getRawType()).isEqualTo(String.class);
});
assertThat(constructor).isNotNull();
assertThat(constructor.getParameters()).hasSize(2);
assertThat(constructor.getParameters().get(0).getRawType()).isEqualTo(Long.class);
assertThat(constructor.getParameters().get(1).getRawType()).isEqualTo(String.class);
}

assertThat(PreferredConstructorDiscoverer.discover(RecordWithNoArgConstructor.class)).satisfies(ctor -> {
@Test // GH-2332
void detectsCanonicalRecordConstructorWhenRecordHasNoArgConstructor() {

assertThat(ctor.getParameters()).hasSize(2);
assertThat(ctor.getParameters().get(0).getRawType()).isEqualTo(Long.class);
assertThat(ctor.getParameters().get(1).getRawType()).isEqualTo(String.class);
});
var constructor = PreferredConstructorDiscoverer.discover(RecordWithNoArgConstructor.class);

assertThat(constructor).isNotNull();
assertThat(constructor.getParameters()).hasSize(2);
assertThat(constructor.getParameters().get(0).getRawType()).isEqualTo(Long.class);
assertThat(constructor.getParameters().get(1).getRawType()).isEqualTo(String.class);
}

@Test // GH-2332
void detectsAnnotatedRecordConstructor() {

assertThat(PreferredConstructorDiscoverer.discover(RecordWithPersistenceCreator.class)).satisfies(ctor -> {
var constructor = PreferredConstructorDiscoverer.discover(RecordWithPersistenceCreator.class);

assertThat(ctor.getParameters()).hasSize(1);
assertThat(ctor.getParameters().get(0).getRawType()).isEqualTo(String.class);
});
assertThat(constructor).isNotNull();
assertThat(constructor.getParameters()).hasSize(1);
assertThat(constructor.getParameters().get(0).getRawType()).isEqualTo(String.class);
}

static class SyntheticConstructor {
@PersistenceConstructor
@PersistenceCreator
private SyntheticConstructor(String x) {}

class InnerSynthetic {
Expand Down Expand Up @@ -220,7 +222,7 @@ public ClassWithMultipleConstructorsAndAnnotation() {}

public ClassWithMultipleConstructorsAndAnnotation(String value) {}

@PersistenceConstructor
@PersistenceCreator
public ClassWithMultipleConstructorsAndAnnotation(Long value) {}
}

Expand Down