Browse Source
We now correctly calculate the number of defaulting masks used to represent constructor arguments. Previously, we've been one off which caused that Kotlin classes with 32/33 parameters weren't able to be instantiated. We also now reuse KotlinDefaultMask to apply defaulting calculation and removed code duplicates.pull/351/head
5 changed files with 233 additions and 17 deletions
@ -0,0 +1,152 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.data.convert; |
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.*; |
||||||
|
|
||||||
|
import java.util.ArrayList; |
||||||
|
import java.util.List; |
||||||
|
import java.util.stream.Collectors; |
||||||
|
import java.util.stream.IntStream; |
||||||
|
|
||||||
|
import org.junit.Test; |
||||||
|
import org.junit.runner.RunWith; |
||||||
|
import org.junit.runners.Parameterized; |
||||||
|
import org.junit.runners.Parameterized.Parameters; |
||||||
|
import org.springframework.data.mapping.PersistentEntity; |
||||||
|
import org.springframework.data.mapping.PreferredConstructor.Parameter; |
||||||
|
import org.springframework.data.mapping.context.SampleMappingContext; |
||||||
|
import org.springframework.data.mapping.context.SamplePersistentProperty; |
||||||
|
import org.springframework.data.mapping.model.BasicPersistentEntity; |
||||||
|
import org.springframework.data.mapping.model.ParameterValueProvider; |
||||||
|
import org.springframework.data.mapping.model.With32Args; |
||||||
|
import org.springframework.data.mapping.model.With33Args; |
||||||
|
import org.springframework.test.util.ReflectionTestUtils; |
||||||
|
|
||||||
|
/** |
||||||
|
* Unit test to verify correct object instantiation using Kotlin defaulting via {@link KotlinClassGeneratingEntityInstantiator}. |
||||||
|
* |
||||||
|
* @author Mark Paluch |
||||||
|
*/ |
||||||
|
@RunWith(Parameterized.class) |
||||||
|
public class ParameterizedKotlinInstantiatorUnitTests { |
||||||
|
|
||||||
|
private final String valueToSet = "THE VALUE"; |
||||||
|
private final PersistentEntity<Object, SamplePersistentProperty> entity; |
||||||
|
private final int propertyCount; |
||||||
|
private final int propertyUnderTestIndex; |
||||||
|
private final String propertyUnderTestName; |
||||||
|
private final EntityInstantiator entityInstantiator; |
||||||
|
|
||||||
|
public ParameterizedKotlinInstantiatorUnitTests(PersistentEntity<Object, SamplePersistentProperty> entity, int propertyCount, int propertyUnderTestIndex, String propertyUnderTestName, EntityInstantiator entityInstantiator, String label) { |
||||||
|
this.entity = entity; |
||||||
|
this.propertyCount = propertyCount; |
||||||
|
this.propertyUnderTestIndex = propertyUnderTestIndex; |
||||||
|
this.propertyUnderTestName = propertyUnderTestName; |
||||||
|
this.entityInstantiator = entityInstantiator; |
||||||
|
} |
||||||
|
|
||||||
|
@Parameters(name = "{5}") |
||||||
|
public static List<Object[]> parameters() { |
||||||
|
|
||||||
|
SampleMappingContext context = new SampleMappingContext(); |
||||||
|
|
||||||
|
KotlinClassGeneratingEntityInstantiator generatingInstantiator = new KotlinClassGeneratingEntityInstantiator(); |
||||||
|
ReflectionEntityInstantiator reflectionInstantiator = ReflectionEntityInstantiator.INSTANCE; |
||||||
|
|
||||||
|
List<Object[]> fixtures = new ArrayList<>(); |
||||||
|
fixtures.addAll(createFixture(context, With32Args.class, 32, generatingInstantiator)); |
||||||
|
fixtures.addAll(createFixture(context, With32Args.class, 32, reflectionInstantiator)); |
||||||
|
fixtures.addAll(createFixture(context, With33Args.class, 33, generatingInstantiator)); |
||||||
|
fixtures.addAll(createFixture(context, With33Args.class, 33, reflectionInstantiator)); |
||||||
|
|
||||||
|
return fixtures; |
||||||
|
} |
||||||
|
|
||||||
|
private static List<Object[]> createFixture(SampleMappingContext context, Class<?> entityType, int propertyCount, EntityInstantiator entityInstantiator) { |
||||||
|
|
||||||
|
BasicPersistentEntity<Object, SamplePersistentProperty> persistentEntity = context.getPersistentEntity(entityType); |
||||||
|
|
||||||
|
return IntStream.range(0, propertyCount).mapToObj(i -> { |
||||||
|
|
||||||
|
return new Object[]{persistentEntity, propertyCount, i, Integer.toString(i), entityInstantiator, String.format("Property %d for %s using %s", i, entityType.getSimpleName(), entityInstantiator.getClass().getSimpleName())}; |
||||||
|
}).collect(Collectors.toList()); |
||||||
|
} |
||||||
|
|
||||||
|
@Test // DATACMNS-1402
|
||||||
|
public void shouldCreateInstanceWithSinglePropertySet() { |
||||||
|
|
||||||
|
Object instance = entityInstantiator.createInstance(entity, new SingleParameterValueProvider()); |
||||||
|
|
||||||
|
for (int i = 0; i < propertyCount; i++) { |
||||||
|
|
||||||
|
Object value = ReflectionTestUtils.getField(instance, Integer.toString(i)); |
||||||
|
|
||||||
|
if (propertyUnderTestIndex == i) { |
||||||
|
assertThat(value).describedAs("Property " + i + " of " + entity).isEqualTo(valueToSet); |
||||||
|
} else { |
||||||
|
assertThat(value).describedAs("Property " + i + " of " + entity).isEqualTo(""); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
@Test // DATACMNS-1402
|
||||||
|
public void shouldCreateInstanceWithAllExceptSinglePropertySet() { |
||||||
|
|
||||||
|
Object instance = entityInstantiator.createInstance(entity, new AllButParameterValueProvider()); |
||||||
|
|
||||||
|
for (int i = 0; i < propertyCount; i++) { |
||||||
|
|
||||||
|
Object value = ReflectionTestUtils.getField(instance, Integer.toString(i)); |
||||||
|
|
||||||
|
if (propertyUnderTestIndex == i) { |
||||||
|
assertThat(value).describedAs("Property " + i + " of " + entity).isEqualTo(""); |
||||||
|
} else { |
||||||
|
assertThat(value).describedAs("Property " + i + " of " + entity).isEqualTo(Integer.toString(i)); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the value to set for the property to test. |
||||||
|
*/ |
||||||
|
class SingleParameterValueProvider implements ParameterValueProvider<SamplePersistentProperty> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> T getParameterValue(Parameter<T, SamplePersistentProperty> parameter) { |
||||||
|
|
||||||
|
if (parameter.getName().equals(propertyUnderTestName)) { |
||||||
|
return (T) valueToSet; |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
/** |
||||||
|
* Return the property name as value for all properties except the one to test. |
||||||
|
*/ |
||||||
|
class AllButParameterValueProvider implements ParameterValueProvider<SamplePersistentProperty> { |
||||||
|
|
||||||
|
@Override |
||||||
|
public <T> T getParameterValue(Parameter<T, SamplePersistentProperty> parameter) { |
||||||
|
|
||||||
|
if (!parameter.getName().equals(propertyUnderTestName)) { |
||||||
|
return (T) parameter.getName(); |
||||||
|
} |
||||||
|
return null; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.data.mapping.model |
||||||
|
|
||||||
|
data class With32Args(val `0`: String = "", val `1`: String = "", val `2`: String = "", val `3`: String = "", val `4`: String = "", val `5`: String = "", |
||||||
|
val `6`: String = "", val `7`: String = "", val `8`: String = "", val `9`: String = "", val `10`: String = "", val `11`: String = "", val `12`: String = "", |
||||||
|
val `13`: String = "", val `14`: String = "", val `15`: String = "", val `16`: String = "", val `17`: String = "", val `18`: String = "", val `19`: String = "", |
||||||
|
val `20`: String = "", val `21`: String = "", val `22`: String = "", val `23`: String = "", val `24`: String = "", val `25`: String = "", val `26`: String = "", |
||||||
|
val `27`: String = "", val `28`: String = "", val `29`: String = "", val `30`: String = "", val `31`: String = "" |
||||||
|
) |
||||||
@ -0,0 +1,23 @@ |
|||||||
|
/* |
||||||
|
* Copyright 2018 the original author or authors. |
||||||
|
* |
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||||
|
* you may not use this file except in compliance with the License. |
||||||
|
* You may obtain a copy of the License at |
||||||
|
* |
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0 |
||||||
|
* |
||||||
|
* Unless required by applicable law or agreed to in writing, software |
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS, |
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||||
|
* See the License for the specific language governing permissions and |
||||||
|
* limitations under the License. |
||||||
|
*/ |
||||||
|
package org.springframework.data.mapping.model |
||||||
|
|
||||||
|
data class With33Args(val `0`: String = "", val `1`: String = "", val `2`: String = "", val `3`: String = "", val `4`: String = "", val `5`: String = "", |
||||||
|
val `6`: String = "", val `7`: String = "", val `8`: String = "", val `9`: String = "", val `10`: String = "", val `11`: String = "", val `12`: String = "", |
||||||
|
val `13`: String = "", val `14`: String = "", val `15`: String = "", val `16`: String = "", val `17`: String = "", val `18`: String = "", val `19`: String = "", |
||||||
|
val `20`: String = "", val `21`: String = "", val `22`: String = "", val `23`: String = "", val `24`: String = "", val `25`: String = "", val `26`: String = "", |
||||||
|
val `27`: String = "", val `28`: String = "", val `29`: String = "", val `30`: String = "", val `31`: String = "", val `32`: String = "" |
||||||
|
) |
||||||
Loading…
Reference in new issue