mtedone / podam

PODAM - POjo DAta Mocker
https://mtedone.github.io/podam
MIT License
326 stars 749 forks source link

Can't generate object when same generic placeholder is used for multiple fields #305

Open lmbnaylor opened 2 years ago

lmbnaylor commented 2 years ago

Problem description: When a class uses a generic type and inherits from a class that uses the same placeholder for a different generic type, generating an object produces an argument mismatch.

Example classes:

public class TestObject<T extends GenericType> extends ParentObject<Short>{

    private T genericType;

    public T getGenericType() {
        return this.genericType;
    }

    public void setGenericType(T genericType) {
        this.genericType = genericType;
    }
}
public class GenericType {
    private String name;

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }
}
public class ParentObject<T extends Serializable> {
    private T id;

    public T getId() {
        return this.id;
    }

    public void setId(T id) {
        this.id = id;
    }
}

Running new PodamFactoryImpl().manufacturePojo(TestObject.class, GenericType.class) produces

Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at uk.co.jemos.podam.api.PodamFactoryImpl.populateReadWriteField(PodamFactoryImpl.java:846)
    at uk.co.jemos.podam.api.PodamFactoryImpl.populatePojoInternal(PodamFactoryImpl.java:615)
    at uk.co.jemos.podam.api.PodamFactoryImpl.manufacturePojoInternal(PodamFactoryImpl.java:525)
    at uk.co.jemos.podam.api.PodamFactoryImpl.doManufacturePojo(PodamFactoryImpl.java:428)
    at uk.co.jemos.podam.api.PodamFactoryImpl.manufacturePojo(PodamFactoryImpl.java:150)
    at org.example.Main.main(Main.java:16)

Because T corresponds to two different types, the typeArgsMap in TypeManufacturerUtil#fillTypeArgMap will add a mapping from T -> GenericType, but gets overridden with T -> Short, so it attempts to populate the genericType field with a Short instead of GenericType

In this simple example, it is trivial to switch the placeholder in ParentObject so there is no overlap, but this remains an issue when you are not able to update the source code; perhaps typeArgsMap could be updated to Map<Class, Map<String, Type>> so that the same placeholder could be used between different classes?