diff --git a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java index fe29c9594..440919981 100644 --- a/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java +++ b/fixture-monkey-api/src/main/java/com/navercorp/fixturemonkey/api/property/ConstructorParameterPropertyGenerator.java @@ -36,6 +36,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -53,6 +54,7 @@ */ @API(since = "0.5.3", status = Status.MAINTAINED) public final class ConstructorParameterPropertyGenerator implements PropertyGenerator { + private final Function>> constructorsSupplier; private final Predicate> constructorPredicate; private final Matcher matcher; @@ -60,15 +62,24 @@ public ConstructorParameterPropertyGenerator( Predicate> constructorPredicate, Matcher matcher ) { + this.constructorsSupplier = p -> TypeCache.getDeclaredConstructors(Types.getActualType(p.getType())); + this.constructorPredicate = constructorPredicate; + this.matcher = matcher; + } + + public ConstructorParameterPropertyGenerator( + Function>> constructorsSupplier, + Predicate> constructorPredicate, + Matcher matcher + ) { + this.constructorsSupplier = constructorsSupplier; this.constructorPredicate = constructorPredicate; this.matcher = matcher; } @Override public List generateChildProperties(Property property) { - Class clazz = Types.getActualType(property.getType()); - - Constructor declaredConstructor = TypeCache.getDeclaredConstructors(clazz).stream() + Constructor declaredConstructor = constructorsSupplier.apply(property).stream() .filter(constructorPredicate) .findFirst() .orElse(null); diff --git a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java index c9761c105..7a598c9cd 100644 --- a/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java +++ b/fixture-monkey-api/src/main/java17/com/navercorp/fixturemonkey/api/option/JdkVariantOptions.java @@ -18,6 +18,7 @@ package com.navercorp.fixturemonkey.api.option; +import java.lang.reflect.Constructor; import java.time.ZoneId; import java.util.List; @@ -26,13 +27,26 @@ import com.navercorp.fixturemonkey.api.matcher.MatcherOperator; import com.navercorp.fixturemonkey.api.property.CandidateConcretePropertyResolver; +import com.navercorp.fixturemonkey.api.property.ConstructorParameterPropertyGenerator; +import com.navercorp.fixturemonkey.api.property.PropertyGenerator; import com.navercorp.fixturemonkey.api.property.SealedTypeCandidateConcretePropertyResolver; +import com.navercorp.fixturemonkey.api.type.Constructors; +import com.navercorp.fixturemonkey.api.type.TypeCache; import com.navercorp.fixturemonkey.api.type.Types; @API(since = "1.0.14", status = Status.INTERNAL) public final class JdkVariantOptions { private static final CandidateConcretePropertyResolver SEALED_TYPE_CANDIDATE_CONCRETE_PROPERTY_RESOLVER = new SealedTypeCandidateConcretePropertyResolver(); + private static final PropertyGenerator CANONICAL_CONSTRUCTOR_PARAMETER_PROPERTY_GENERATOR = + new ConstructorParameterPropertyGenerator( + p -> Constructors.findPrimaryConstructor( + Types.getActualType(p.getType()), + TypeCache.getDeclaredConstructors(Types.getActualType(p.getType())).toArray(Constructor[]::new) + ).stream().toList(), + it -> true, + it -> true + ); public void apply(FixtureMonkeyOptionsBuilder optionsBuilder) { optionsBuilder.insertFirstCandidateConcretePropertyResolvers( @@ -41,6 +55,10 @@ public void apply(FixtureMonkeyOptionsBuilder optionsBuilder) { SEALED_TYPE_CANDIDATE_CONCRETE_PROPERTY_RESOLVER ) ) - .insertFirstPropertyGenerator(ZoneId.class, property -> List.of()); + .insertFirstPropertyGenerator(ZoneId.class, property -> List.of()) + .insertFirstPropertyGenerator( + p -> Types.getActualType(p.getType()).isRecord(), + CANONICAL_CONSTRUCTOR_PARAMETER_PROPERTY_GENERATOR + ); } } diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java index 3015ad769..16c023bfb 100644 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/ConstructorPropertiesRecordTest.java @@ -27,6 +27,7 @@ import com.navercorp.fixturemonkey.FixtureMonkey; import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitraryIntrospector; import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.BooleanRecord; +import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.CanonicalConstructorRecord; import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.CompactConstructorRecord; import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.ComplexContainerRecord; import com.navercorp.fixturemonkey.tests.java17.RecordTestSpecs.ContainerRecord; @@ -39,6 +40,7 @@ class ConstructorPropertiesRecordTest { private static final FixtureMonkey SUT = FixtureMonkey.builder() .objectIntrospector(ConstructorPropertiesArbitraryIntrospector.INSTANCE) + .defaultNotNull(true) .build(); @RepeatedTest(TEST_COUNT) @@ -205,4 +207,11 @@ void setWrapperBoolean() { then(actual).isFalse(); } + + @RepeatedTest(TEST_COUNT) + void sampleCanonicalConstructorRecord() { + String actual = SUT.giveMeOne(CanonicalConstructorRecord.class).string(); + + then(actual).isNotNull(); + } } diff --git a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/RecordTestSpecs.java b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/RecordTestSpecs.java index c18bca8e0..e7674f930 100644 --- a/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/RecordTestSpecs.java +++ b/fixture-monkey-tests/java-17-tests/src/test/java/com/navercorp/fixturemonkey/tests/java17/RecordTestSpecs.java @@ -158,4 +158,10 @@ public record IsPrefixBooleanRecord(boolean isPrimitive, Boolean isWrapper) { public record BooleanRecord(boolean primitive, Boolean wrapper) { } + + public record CanonicalConstructorRecord(String string) { + public CanonicalConstructorRecord() { + this(null); + } + } }