• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * The MIT License
3  *
4  * Copyright (c) 2018 Niek Haarman
5  * Copyright (c) 2007 Mockito contributors
6  *
7  * Permission is hereby granted, free of charge, to any person obtaining a copy
8  * of this software and associated documentation files (the "Software"), to deal
9  * in the Software without restriction, including without limitation the rights
10  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11  * copies of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be included in
15  * all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23  * THE SOFTWARE.
24  */
25 
26 package org.mockito.kotlin
27 
28 import org.mockito.kotlin.internal.createInstance
29 import org.mockito.ArgumentCaptor
30 import kotlin.reflect.KClass
31 
32 /**
33  * Creates a [KArgumentCaptor] for given type.
34  */
argumentCaptornull35 inline fun <reified T : Any> argumentCaptor(): KArgumentCaptor<T> {
36     return KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class)
37 }
38 
39 /**
40  * Creates 2 [KArgumentCaptor]s for given types.
41  */
argumentCaptornull42 inline fun <reified A : Any, reified B : Any> argumentCaptor(
43     a: KClass<A> = A::class,
44     b: KClass<B> = B::class
45 ): Pair<KArgumentCaptor<A>, KArgumentCaptor<B>> {
46     return Pair(
47           KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
48           KArgumentCaptor(ArgumentCaptor.forClass(b.java), b)
49     )
50 }
51 
52 /**
53  * Creates 3 [KArgumentCaptor]s for given types.
54  */
argumentCaptornull55 inline fun <reified A : Any, reified B : Any, reified C : Any> argumentCaptor(
56     a: KClass<A> = A::class,
57     b: KClass<B> = B::class,
58     c: KClass<C> = C::class
59 ): Triple<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>> {
60     return Triple(
61           KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
62           KArgumentCaptor(ArgumentCaptor.forClass(b.java), b),
63           KArgumentCaptor(ArgumentCaptor.forClass(c.java), c)
64     )
65 }
66 
67 class ArgumentCaptorHolder4<out A, out B, out C, out D>(
68     val first: A,
69     val second: B,
70     val third: C,
71     val fourth: D
72 ) {
73 
component1null74     operator fun component1() = first
75     operator fun component2() = second
76     operator fun component3() = third
77     operator fun component4() = fourth
78 }
79 
80 class ArgumentCaptorHolder5<out A, out B, out C, out D, out E>(
81     val first: A,
82     val second: B,
83     val third: C,
84     val fourth: D,
85     val fifth: E
86 ) {
87 
88     operator fun component1() = first
89     operator fun component2() = second
90     operator fun component3() = third
91     operator fun component4() = fourth
92     operator fun component5() = fifth
93 }
94 
95 
96 /**
97  * Creates 4 [KArgumentCaptor]s for given types.
98  */
argumentCaptornull99 inline 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
104 ): ArgumentCaptorHolder4<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>> {
105     return ArgumentCaptorHolder4(
106           KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
107           KArgumentCaptor(ArgumentCaptor.forClass(b.java), b),
108           KArgumentCaptor(ArgumentCaptor.forClass(c.java), c),
109           KArgumentCaptor(ArgumentCaptor.forClass(d.java), d)
110     )
111 }
112 
113 /**
114  * Creates 4 [KArgumentCaptor]s for given types.
115  */
argumentCaptornull116 inline 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
122 ): ArgumentCaptorHolder5<KArgumentCaptor<A>, KArgumentCaptor<B>, KArgumentCaptor<C>, KArgumentCaptor<D>, KArgumentCaptor<E>> {
123     return ArgumentCaptorHolder5(
124           KArgumentCaptor(ArgumentCaptor.forClass(a.java), a),
125           KArgumentCaptor(ArgumentCaptor.forClass(b.java), b),
126           KArgumentCaptor(ArgumentCaptor.forClass(c.java), c),
127           KArgumentCaptor(ArgumentCaptor.forClass(d.java), d),
128           KArgumentCaptor(ArgumentCaptor.forClass(e.java), e)
129     )
130 }
131 
132 /**
133  * Creates a [KArgumentCaptor] for given type, taking in a lambda to allow fast verification.
134  */
argumentCaptornull135 inline fun <reified T : Any> argumentCaptor(f: KArgumentCaptor<T>.() -> Unit): KArgumentCaptor<T> {
136     return argumentCaptor<T>().apply(f)
137 }
138 
139 /**
140  * Creates a [KArgumentCaptor] for given nullable type.
141  */
nullableArgumentCaptornull142 inline fun <reified T : Any> nullableArgumentCaptor(): KArgumentCaptor<T?> {
143     return KArgumentCaptor(ArgumentCaptor.forClass(T::class.java), T::class)
144 }
145 
146 /**
147  * Creates a [KArgumentCaptor] for given nullable type, taking in a lambda to allow fast verification.
148  */
nullableArgumentCaptornull149 inline fun <reified T : Any> nullableArgumentCaptor(f: KArgumentCaptor<T?>.() -> Unit): KArgumentCaptor<T?> {
150     return nullableArgumentCaptor<T>().apply(f)
151 }
152 
153 /**
154  * Alias for [ArgumentCaptor.capture].
155  */
capturenull156 inline fun <reified T : Any> capture(captor: ArgumentCaptor<T>): T {
157     return captor.capture() ?: createInstance()
158 }
159 
160 class KArgumentCaptor<out T : Any?>(
161     private val captor: ArgumentCaptor<T>,
162     private val tClass: KClass<*>
163 ) {
164 
165     /**
166      * The first captured value of the argument.
167      * @throws IndexOutOfBoundsException if the value is not available.
168      */
169     val firstValue: T
170         get() = captor.firstValue
171 
172     /**
173      * The second captured value of the argument.
174      * @throws IndexOutOfBoundsException if the value is not available.
175      */
176     val secondValue: T
177         get() = captor.secondValue
178 
179     /**
180      * The third captured value of the argument.
181      * @throws IndexOutOfBoundsException if the value is not available.
182      */
183     val thirdValue: T
184         get() = captor.thirdValue
185 
186     /**
187      * The last captured value of the argument.
188      * @throws IndexOutOfBoundsException if the value is not available.
189      */
190     val lastValue: T
191         get() = captor.lastValue
192 
193     val allValues: List<T>
194         get() = captor.allValues
195 
196     @Suppress("UNCHECKED_CAST")
capturenull197     fun capture(): T {
198         return captor.capture() ?: createInstance(tClass) as T
199     }
200 }
201 
202 val <T> ArgumentCaptor<T>.firstValue: T
203     get() = allValues[0]
204 
205 val <T> ArgumentCaptor<T>.secondValue: T
206     get() = allValues[1]
207 
208 val <T> ArgumentCaptor<T>.thirdValue: T
209     get() = allValues[2]
210 
211 val <T> ArgumentCaptor<T>.lastValue: T
212     get() = allValues.last()
213