2525
2626package org.mockito.kotlin
2727
28- import org.mockito.kotlin.internal.createInstance
2928import org.mockito.ArgumentCaptor
29+ import org.mockito.kotlin.internal.createInstance
3030import java.lang.reflect.Array
3131import kotlin.reflect.KClass
32+ import kotlin.reflect.KType
33+ import kotlin.reflect.typeOf
3234
3335/* *
3436 * Creates a [KArgumentCaptor] for given type.
3537 */
36- inline fun <reified T : Any > argumentCaptor (): KArgumentCaptor <T > {
37- return KArgumentCaptor (T :: class )
38+ inline fun <reified T : Any ? > argumentCaptor (): KArgumentCaptor <T > {
39+ return KArgumentCaptor (typeOf< T >() )
3840}
3941
4042/* *
4143 * Creates 2 [KArgumentCaptor]s for given types.
4244 */
4345inline fun <reified A : Any , reified B : Any > argumentCaptor (
44- a : KClass <A > = A : :class,
45- b : KClass <B > = B : :class
46+ @Suppress( " unused " ) a : KClass <A > = A : :class,
47+ @Suppress( " unused " ) b : KClass <B > = B : :class
4648): Pair <KArgumentCaptor <A >, KArgumentCaptor<B>> {
4749 return Pair (
48- KArgumentCaptor (a ),
49- KArgumentCaptor (b )
50+ KArgumentCaptor (typeOf< A >() ),
51+ KArgumentCaptor (typeOf< B >() )
5052 )
5153}
5254
5355/* *
5456 * Creates 3 [KArgumentCaptor]s for given types.
5557 */
5658inline fun <reified A : Any , reified B : Any , reified C : Any > argumentCaptor (
57- a : KClass <A > = A : :class,
58- b : KClass <B > = B : :class,
59- c : KClass <C > = C : :class
59+ @Suppress( " unused " ) a : KClass <A > = A : :class,
60+ @Suppress( " unused " ) b : KClass <B > = B : :class,
61+ @Suppress( " unused " ) c : KClass <C > = C : :class
6062): Triple <KArgumentCaptor <A >, KArgumentCaptor<B>, KArgumentCaptor<C>> {
6163 return Triple (
62- KArgumentCaptor (a ),
63- KArgumentCaptor (b ),
64- KArgumentCaptor (c )
64+ KArgumentCaptor (typeOf< A >() ),
65+ KArgumentCaptor (typeOf< B >() ),
66+ KArgumentCaptor (typeOf< C >() )
6567 )
6668}
6769
@@ -97,35 +99,35 @@ class ArgumentCaptorHolder5<out A, out B, out C, out D, out E>(
9799 * Creates 4 [KArgumentCaptor]s for given types.
98100 */
99101inline fun <reified A : Any , reified B : Any , reified C : Any , reified D : Any > argumentCaptor (
100- a : KClass <A > = A : :class,
101- b : KClass <B > = B : :class,
102- c : KClass <C > = C : :class,
103- d : KClass <D > = D : :class
102+ @Suppress( " unused " ) a : KClass <A > = A : :class,
103+ @Suppress( " unused " ) b : KClass <B > = B : :class,
104+ @Suppress( " unused " ) c : KClass <C > = C : :class,
105+ @Suppress( " unused " ) d : KClass <D > = D : :class
104106): ArgumentCaptorHolder4 <KArgumentCaptor <A >, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>> {
105107 return ArgumentCaptorHolder4 (
106- KArgumentCaptor (a ),
107- KArgumentCaptor (b ),
108- KArgumentCaptor (c ),
109- KArgumentCaptor (d )
108+ KArgumentCaptor (typeOf< A >() ),
109+ KArgumentCaptor (typeOf< B >() ),
110+ KArgumentCaptor (typeOf< C >() ),
111+ KArgumentCaptor (typeOf< D >() )
110112 )
111113}
112114
113115/* *
114116 * Creates 4 [KArgumentCaptor]s for given types.
115117 */
116118inline fun <reified A : Any , reified B : Any , reified C : Any , reified D : Any , reified E : Any > argumentCaptor (
117- a : KClass <A > = A : :class,
118- b : KClass <B > = B : :class,
119- c : KClass <C > = C : :class,
120- d : KClass <D > = D : :class,
121- e : KClass <E > = E : :class
119+ @Suppress( " unused " ) a : KClass <A > = A : :class,
120+ @Suppress( " unused " ) b : KClass <B > = B : :class,
121+ @Suppress( " unused " ) c : KClass <C > = C : :class,
122+ @Suppress( " unused " ) d : KClass <D > = D : :class,
123+ @Suppress( " unused " ) e : KClass <E > = E : :class
122124): ArgumentCaptorHolder5 <KArgumentCaptor <A >, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>, KArgumentCaptor<E>> {
123125 return ArgumentCaptorHolder5 (
124- KArgumentCaptor (a ),
125- KArgumentCaptor (b ),
126- KArgumentCaptor (c ),
127- KArgumentCaptor (d ),
128- KArgumentCaptor (e )
126+ KArgumentCaptor (typeOf< A >() ),
127+ KArgumentCaptor (typeOf< B >() ),
128+ KArgumentCaptor (typeOf< C >() ),
129+ KArgumentCaptor (typeOf< D >() ),
130+ KArgumentCaptor (typeOf< E >() )
129131 )
130132}
131133
@@ -140,7 +142,7 @@ inline fun <reified T : Any> argumentCaptor(f: KArgumentCaptor<T>.() -> Unit): K
140142 * Creates a [KArgumentCaptor] for given nullable type.
141143 */
142144inline fun <reified T : Any > nullableArgumentCaptor (): KArgumentCaptor <T ?> {
143- return KArgumentCaptor (T :: class )
145+ return KArgumentCaptor (typeOf< T >() )
144146}
145147
146148/* *
@@ -157,17 +159,17 @@ inline fun <reified T : Any> capture(captor: ArgumentCaptor<T>): T {
157159 return captor.capture() ? : createInstance()
158160}
159161
160- class KArgumentCaptor <out T : Any ?> (
161- private val tClass : KClass <* >
162- ) {
162+ class KArgumentCaptor <out T : Any ?>( private val kType : KType ) {
163+ private val clazz = kType.classifier as KClass <* >
164+
163165 private val captor: ArgumentCaptor <Any ?> =
164- if (tClass .isValue) {
166+ if (clazz .isValue && ! kType.isMarkedNullable ) {
165167 val boxImpl =
166- tClass .java.declaredMethods
168+ clazz .java.declaredMethods
167169 .single { it.name == " box-impl" && it.parameterCount == 1 }
168170 boxImpl.parameters[0 ].type // is the boxed type of the value type
169171 } else {
170- tClass .java
172+ clazz .java
171173 }.let {
172174 ArgumentCaptor .forClass(it)
173175 }
@@ -219,27 +221,29 @@ class KArgumentCaptor<out T : Any?> (
219221 // In Java, `captor.capture` returns null and so the method is called with `[null]`
220222 // In Kotlin, we have to create `[null]` explicitly.
221223 // This code-path is applied for non-vararg array arguments as well, but it seems to work fine.
222- return captor.capture() as T ? : if (tClass .java.isArray) {
224+ return toKotlinType( captor.capture()) ? : if (clazz .java.isArray) {
223225 singleElementArray()
224226 } else {
225- createInstance(tClass )
227+ createInstance(clazz )
226228 } as T
227229 }
228230
229- private fun singleElementArray (): Any? = Array .newInstance(tClass .java.componentType, 1 )
231+ private fun singleElementArray (): Any? = Array .newInstance(clazz .java.componentType, 1 )
230232
231233 @Suppress(" UNCHECKED_CAST" )
232- private fun toKotlinType (rawCapturedValue : Any? ) : T {
233- return if (tClass.isValue) {
234- rawCapturedValue
235- ?.let {
234+ private fun toKotlinType (rawCapturedValue : Any? ): T {
235+ if (rawCapturedValue == null ) return null as T
236+
237+ if (clazz.isValue && rawCapturedValue::class != clazz) {
238+ return rawCapturedValue
239+ .let {
236240 val boxImpl =
237- tClass .java.declaredMethods.single { it.name == " box-impl" && it.parameterCount == 1 }
241+ clazz .java.declaredMethods.single { it.name == " box-impl" && it.parameterCount == 1 }
238242 boxImpl.invoke(null , it)
239243 } as T
240- } else {
241- rawCapturedValue as T
242244 }
245+
246+ return rawCapturedValue as T
243247 }
244248}
245249
0 commit comments