Fix BeanUtils#instantiateClass w/ Kotlin + noarg constructor

Issue: SPR-15851
This commit is contained in:
Sebastien Deleuze 2017-08-14 15:14:02 +02:00
parent f57e5584af
commit ef175d7ca6
2 changed files with 21 additions and 13 deletions

View File

@ -734,12 +734,11 @@ public abstract class BeanUtils {
* Instantiate a Kotlin class using the provided constructor.
* @param ctor the constructor of the Kotlin class to instantiate
* @param args the constructor arguments to apply (use null for unspecified parameter if needed)
* @throws BeanInstantiationException if no primary constructor can be found
*/
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) {
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
KFunction<T> kotlinConstructor = ReflectJvmMapping.getKotlinFunction(ctor);
if (kotlinConstructor == null) {
throw new BeanInstantiationException(ctor.getDeclaringClass(), "No corresponding Kotlin constructor found");
return ctor.newInstance(args);
}
List<KParameter> parameters = kotlinConstructor.getParameters();
Map<KParameter, Object> argParameters = new HashMap<>(parameters.size());

View File

@ -29,37 +29,46 @@ class BeanUtilsKotlinTests {
@Test
fun `Instantiate immutable class`() {
val constructor = BeanUtils.findPrimaryConstructor(Foo::class.java)!!
val foo = BeanUtils.instantiateClass(constructor, "bar", 3)
assertEquals("bar", foo.param1)
val foo = BeanUtils.instantiateClass(constructor, "a", 3)
assertEquals("a", foo.param1)
assertEquals(3, foo.param2)
}
@Test
fun `Instantiate immutable class with optional parameter and all parameters specified`() {
val constructor = BeanUtils.findPrimaryConstructor(Bar::class.java)!!
val bar = BeanUtils.instantiateClass(constructor, "baz", 8)
assertEquals("baz", bar.param1)
val bar = BeanUtils.instantiateClass(constructor, "a", 8)
assertEquals("a", bar.param1)
assertEquals(8, bar.param2)
}
@Test
fun `Instantiate immutable class with optional parameter and only mandatory parameters specified by position`() {
val constructor = BeanUtils.findPrimaryConstructor(Bar::class.java)!!
val bar = BeanUtils.instantiateClass(constructor, "baz")
assertEquals("baz", bar.param1)
val bar = BeanUtils.instantiateClass(constructor, "a")
assertEquals("a", bar.param1)
assertEquals(12, bar.param2)
}
@Test
fun `Instantiate immutable class with optional parameter specified with null value`() {
fun `Instantiate immutable class with optional parameter specified with null value`() {
val constructor = BeanUtils.findPrimaryConstructor(Bar::class.java)!!
val bar = BeanUtils.instantiateClass(constructor, "baz", null)
assertEquals("baz", bar.param1)
val bar = BeanUtils.instantiateClass(constructor, "a", null)
assertEquals("a", bar.param1)
assertEquals(12, bar.param2)
}
@Test // SPR-15851
fun `Instantiate mutable class with declared constructor and default values for all parameters`() {
val baz = BeanUtils.instantiateClass(Baz::class.java.getDeclaredConstructor())
assertEquals("a", baz.param1)
assertEquals(12, baz.param2)
}
class Foo(val param1: String, val param2: Int)
class Bar(val param1: String, val param2: Int = 12)
class Baz(var param1: String = "a", var param2: Int = 12)
}