Skip to content

Commit ea0263d

Browse files
committed
Avoid constructors with an array as a parameter.
The UUID class has a single-argument constructor which expects an array with some specific contents. This commit tries to avoid these type of constructors, since it may be a common case. Instead, it tries to find a constructor without an array parameter, or otherwise falls back. Fixes issue #17.
1 parent 48fc1aa commit ea0263d

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

mockito-kotlin/src/main/kotlin/com/nhaarman/mockito_kotlin/CreateInstance.kt

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,30 @@ fun <T : Any> createInstance(kClass: KClass<T>): T {
5454
kClass.isPrimitive() -> kClass.toDefaultPrimitiveValue()
5555
kClass.isEnum() -> kClass.java.enumConstants.first()
5656
kClass.isArray() -> kClass.toArrayInstance()
57-
else -> kClass.constructors.sortedBy { it.parameters.size }.first().newInstance()
57+
else -> kClass.easiestConstructor().newInstance()
5858
}
5959
}
6060

61+
/**
62+
* Tries to find the easiest constructor which it can instantiate.
63+
*/
64+
private fun <T : Any> KClass<T>.easiestConstructor(): KFunction<T> {
65+
return constructors.firstOrDefault(
66+
{
67+
it.parameters.filter {
68+
it.type.toString().toLowerCase().contains("array")
69+
}.isEmpty()
70+
},
71+
{
72+
constructors.sortedBy { it.parameters.size }.first()
73+
}
74+
)
75+
}
76+
77+
private fun <T> Collection<T>.firstOrDefault(predicate: (T) -> Boolean, default: () -> T): T {
78+
return firstOrNull(predicate) ?: default()
79+
}
80+
6181
@Suppress("SENSELESS_COMPARISON")
6282
private fun KClass<*>.hasObjectInstance() = objectInstance != null
6383

mockito-kotlin/src/test/kotlin/CreateInstanceTest.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import com.nhaarman.expect.expect
2727
import com.nhaarman.mockito_kotlin.createInstance
2828
import org.junit.Test
29+
import java.util.*
2930

3031
class CreateInstanceTest {
3132

@@ -368,6 +369,21 @@ class CreateInstanceTest {
368369
expect(result).toNotBeNull()
369370
}
370371

372+
@Test
373+
fun uuid() {
374+
/**
375+
* The UUID class has a single-argument constructor that expects an array with some specific contents.
376+
* We avoid these types of constructors by calling another constructor, if available.
377+
* In this case, UUID(Long, Long).
378+
*/
379+
380+
/* When */
381+
val result = createInstance<UUID>()
382+
383+
/* Then */
384+
expect(result).toBeEqualTo(UUID(0, 0))
385+
}
386+
371387
private class PrivateClass private constructor(val data: String)
372388

373389
class ClosedClass

0 commit comments

Comments
 (0)