Skip to content

Commit

Permalink
Fix setting a child of a concrete type to an abstract type (#960)
Browse files Browse the repository at this point in the history
  • Loading branch information
seongahjo authored Mar 26, 2024
1 parent 4c26bbd commit 83a2f01
Show file tree
Hide file tree
Showing 4 changed files with 59 additions and 15 deletions.
4 changes: 4 additions & 0 deletions docs/content/v1.0.x-kor/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions docs/content/v1.0.x/release-notes/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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<AbstractClass>()
.set("$", ConcreteTypeChild(""))
.sample()

then(actual).isExactlyInstanceOf(ConcreteTypeChild::class.java)
}

companion object {
private val SUT: FixtureMonkey = FixtureMonkey.builder()
.plugin(KotlinPlugin())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<Property> 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<ConcreteTypeDefinition> 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<Property> 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));
}
}
}
}
}
Expand Down

0 comments on commit 83a2f01

Please sign in to comment.