ocadotechnology / test-arranger

Arranges test data as fully populated objects
Apache License 2.0
23 stars 2 forks source link

Overriding primitive fields in records leads to exception #67

Open mjureczko opened 2 weeks ago

mjureczko commented 2 weeks ago

Given:

public record SomeRecord(double someValue);

When:

some(SomeRecord.class, Map.of("someValue", () -> 1.0);

Then: the following exception is thrown

Unable to create a random instance of type class com.ocado.cubing.approximate.client.cfccubing.dto.PreCubedFulfillmentDto$BagDto
org.jeasy.random.ObjectCreationException: Unable to create a random instance of type class com.ocado.cubing.approximate.client.cfccubing.dto.PreCubedFulfillmentDto$BagDto
    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:188)
    at org.jeasy.random.EasyRandom.nextObject(EasyRandom.java:109)
    at com.ocadotechnology.gembus.test.EnhancedRandom.lambda$nextObject$0(EnhancedRandom.java:81)
    at com.ocadotechnology.gembus.test.NestingSafeExecutor.execute(NestingSafeExecutor.java:29)
    at com.ocadotechnology.gembus.test.EnhancedRandom.nextObject(EnhancedRandom.java:81)
    at com.ocadotechnology.gembus.test.Arranger.some(Arranger.java:65)
...
Caused by: org.jeasy.random.ObjectCreationException: Unable to create a random instance of recordType class com.ocado.cubing.approximate.client.cfccubing.dto.PreCubedFulfillmentDto$BagDto
    at org.jeasy.random.RecordFactory.createRandomRecord(RecordFactory.java:96)
    at org.jeasy.random.RecordFactory.createInstance(RecordFactory.java:58)
    at org.jeasy.random.EasyRandom.doPopulateBean(EasyRandom.java:149)
    ... 160 more
Caused by: java.lang.IllegalArgumentException: java.lang.NullPointerException: Cannot invoke "java.lang.Number.doubleValue()" because the return value of "sun.invoke.util.ValueConversions.primitiveConversion(sun.invoke.util.Wrapper, Object, boolean)" is null
    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:70)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:502)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:486)
    at org.jeasy.random.RecordFactory.createRandomRecord(RecordFactory.java:94)
    ... 162 more
Caused by: java.lang.NullPointerException: Cannot invoke "java.lang.Number.doubleValue()" because the return value of "sun.invoke.util.ValueConversions.primitiveConversion(sun.invoke.util.Wrapper, Object, boolean)" is null
    at java.base/sun.invoke.util.ValueConversions.unboxDouble(ValueConversions.java:144)
    at java.base/jdk.internal.reflect.DirectConstructorHandleAccessor.newInstance(DirectConstructorHandleAccessor.java:62)
    ... 165 more

It is a consequence of passing as toIgnore the fields that should be overriden in:

    public static <T> T some(final Class<T> type, final Map<String, Supplier<?>> overrides) {
        CurrentEnhancedRandom.set(random);
        String[] toIgnore = overrides.keySet().toArray(new String[overrides.size()]);
        T result = random.nextObject(type, toIgnore);
        if (type.isRecord()) {
            return Data.copy(result, overrides);
        } else {
            OverridesHelper.applyOverrides(result, overrides);
            return result;
        }
    }

There is a workaround with using Data.copy() in place of overrides.