diff --git a/docs/content/v1.0.x-kor/release-notes/_index.md b/docs/content/v1.0.x-kor/release-notes/_index.md index 8921615e5..a88867a73 100644 --- a/docs/content/v1.0.x-kor/release-notes/_index.md +++ b/docs/content/v1.0.x-kor/release-notes/_index.md @@ -10,6 +10,10 @@ sectionStart ### v.1.0.15 Add `ConcreteTypeDefinition` in `ArbitraryProperty`, deprecate `getChildPropertiesByResolvedProperty` and `getChildPropertyListsByCandidateProperty` which is added in 1.0.14. +Add "KotlinDurationIntrospector" supporting generating a Duration type in Kotlin. + +Fix setting a child of a concrete type to an abstract type. + sectionEnd sectionStart diff --git a/docs/content/v1.0.x/release-notes/_index.md b/docs/content/v1.0.x/release-notes/_index.md index 6455ee21a..5b2ab579f 100644 --- a/docs/content/v1.0.x/release-notes/_index.md +++ b/docs/content/v1.0.x/release-notes/_index.md @@ -12,6 +12,8 @@ Add `ConcreteTypeDefinition` in `ArbitraryProperty`, deprecate `getChildProperti Add "KotlinDurationIntrospector" supporting generating a Duration type in Kotlin. +Fix setting a child of a concrete type to an abstract type. + sectionEnd sectionStart diff --git a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinTest.kt b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinTest.kt index 916fe0bee..2571ccdc7 100644 --- a/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinTest.kt +++ b/fixture-monkey-tests/kotlin-tests/src/test/kotlin/com/navercorp/fixturemonkey/tests/kotlin/KotlinTest.kt @@ -30,6 +30,7 @@ import com.navercorp.fixturemonkey.api.introspector.ConstructorPropertiesArbitra import com.navercorp.fixturemonkey.api.introspector.FactoryMethodArbitraryIntrospector import com.navercorp.fixturemonkey.api.introspector.FailoverIntrospector import com.navercorp.fixturemonkey.api.introspector.FieldReflectionArbitraryIntrospector +import com.navercorp.fixturemonkey.api.plugin.InterfacePlugin import com.navercorp.fixturemonkey.api.type.Types.GeneratingWildcardType import com.navercorp.fixturemonkey.customizer.Values import com.navercorp.fixturemonkey.kotlin.KotlinPlugin @@ -424,6 +425,32 @@ class KotlinTest { then(actual).isNotNull } + @RepeatedTest(TEST_COUNT) + fun setConcreteTypeChildReturnsExactlyConcreteTypeChildType() { + // given + abstract class AbstractClass + open class ConcreteType(val parentValue: String) : AbstractClass() + class ConcreteTypeChild(val childValue: String) : ConcreteType("parent") + + val sut = FixtureMonkey.builder() + .plugin(KotlinPlugin()) + .plugin( + InterfacePlugin() + .abstractClassExtends( + AbstractClass::class.java, + listOf(ConcreteType::class.java, ConcreteTypeChild::class.java) + ) + ) + .build() + + // when + val actual = sut.giveMeBuilder() + .set("$", ConcreteTypeChild("")) + .sample() + + then(actual).isExactlyInstanceOf(ConcreteTypeChild::class.java) + } + companion object { private val SUT: FixtureMonkey = FixtureMonkey.builder() .plugin(KotlinPlugin()) diff --git a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java index 77f7777d2..e080ed6f0 100644 --- a/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java +++ b/fixture-monkey/src/main/java/com/navercorp/fixturemonkey/customizer/NodeSetDecomposedValueManipulator.java @@ -148,21 +148,32 @@ private void setValue(ObjectNode objectNode, @Nullable Object value) { return; } - ConcreteTypeDefinition concreteTypeDefinition = objectNode.getArbitraryProperty() - .getConcreteTypeDefinitions() - .stream() - .filter(it -> isAssignable(value.getClass(), Types.getActualType(it.getConcreteProperty().getType()))) - .findFirst() - .orElseThrow(() -> new IllegalArgumentException("No resolved property is found.")); - - Property resolvedParentProperty = concreteTypeDefinition.getConcreteProperty(); - objectNode.setResolvedProperty(resolvedParentProperty); - List childProperties = concreteTypeDefinition.getChildPropertyLists(); - for (ObjectNode child : children) { - if (childProperties.contains(child.getProperty()) - && resolvedParentProperty.equals(child.getResolvedParentProperty())) { - Property childProperty = child.getProperty(); - setValue(child, childProperty.getValue(value)); + List concreteTypeDefinitions = objectNode.getArbitraryProperty() + .getConcreteTypeDefinitions(); + + for (ConcreteTypeDefinition concreteTypeDefinition : concreteTypeDefinitions) { + Class actualConcreteType = Types.getActualType(concreteTypeDefinition.getConcreteProperty().getType()); + if (isAssignable( + value.getClass(), + actualConcreteType + )) { + Property resolvedParentProperty = concreteTypeDefinition.getConcreteProperty(); + + if (isAssignable( + actualConcreteType, + value.getClass() + )) { + objectNode.setResolvedProperty(resolvedParentProperty); + } + + List childProperties = concreteTypeDefinition.getChildPropertyLists(); + for (ObjectNode child : children) { + if (childProperties.contains(child.getProperty()) + && resolvedParentProperty.equals(child.getResolvedParentProperty())) { + Property childProperty = child.getProperty(); + setValue(child, childProperty.getValue(value)); + } + } } } }