1 /*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.systemui.util.mockito
18
19 /**
20 * Kotlin versions of popular mockito methods that can return null in situations when Kotlin expects
21 * a non-null value. Kotlin will throw an IllegalStateException when this takes place ("x must not
22 * be null"). To fix this, we can use methods that modify the return type to be nullable. This
23 * causes Kotlin to skip the null checks.
24 */
25 import kotlin.DeprecationLevel.WARNING
26 import org.mockito.ArgumentCaptor
27 import org.mockito.ArgumentMatcher
28 import org.mockito.MockSettings
29 import org.mockito.Mockito
30 import org.mockito.Mockito.`when`
31 import org.mockito.Mockito.withSettings
32 import org.mockito.stubbing.OngoingStubbing
33 import org.mockito.stubbing.Stubber
34
35 /**
36 * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when null is
37 * returned.
38 *
39 * Generic T is nullable because implicitly bounded by Any?.
40 */
41 @Deprecated(
42 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
43 ReplaceWith(expression = "eq", imports = ["org.mockito.kotlin.eq"]),
44 level = WARNING
45 )
eqnull46 fun <T> eq(obj: T): T = Mockito.eq<T>(obj) ?: obj
47
48 /**
49 * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when null is
50 * returned.
51 *
52 * Generic T is nullable because implicitly bounded by Any?.
53 */
54 @Deprecated(
55 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
56 ReplaceWith(expression = "any(type)", imports = ["org.mockito.kotlin.any"]),
57 level = WARNING
58 )
59 fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
60
61 @Deprecated(
62 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
63 ReplaceWith(expression = "any()", imports = ["org.mockito.kotlin.any"]),
64 level = WARNING
65 )
66 inline fun <reified T> any(): T = any(T::class.java)
67
68 /**
69 * Returns Mockito.argThat() as nullable type to avoid java.lang.IllegalStateException when null is
70 * returned.
71 *
72 * Generic T is nullable because implicitly bounded by Any?.
73 */
74 @Deprecated(
75 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
76 ReplaceWith(expression = "argThat(matcher)", imports = ["org.mockito.kotlin.argThat"]),
77 level = WARNING
78 )
79 fun <T> argThat(matcher: ArgumentMatcher<T>): T = Mockito.argThat(matcher)
80
81 /**
82 * Kotlin type-inferred version of Mockito.nullable()
83 *
84 * @see org.mockito.kotlin.anyOrNull
85 */
86 @Deprecated(
87 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
88 ReplaceWith(expression = "anyOrNull()", imports = ["org.mockito.kotlin.anyOrNull"]),
89 level = WARNING
90 )
91 inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
92
93 /**
94 * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException when
95 * null is returned.
96 *
97 * Generic T is nullable because implicitly bounded by Any?.
98 *
99 * @see org.mockito.kotlin.capture
100 */
101 @Deprecated(
102 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
103 ReplaceWith(expression = "capture(argumentCaptor)", imports = ["org.mockito.kotlin.capture"]),
104 level = WARNING
105 )
106 fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
107
108 /**
109 * Helper function for creating an argumentCaptor in kotlin.
110 *
111 * Generic T is nullable because implicitly bounded by Any?.
112 *
113 * @see org.mockito.kotlin.argumentCaptor
114 */
115 @Deprecated(
116 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
117 ReplaceWith(expression = "argumentCaptor()", imports = ["org.mockito.kotlin.argumentCaptor"]),
118 level = WARNING
119 )
120 inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
121 ArgumentCaptor.forClass(T::class.java)
122
123 /**
124 * Helper function for creating new mocks, without the need to pass in a [Class] instance.
125 *
126 * Generic T is nullable because implicitly bounded by Any?.
127 *
128 * Updated kotlin-mockito usage:
129 * ```
130 * val value: Widget = mock<> {
131 * on { status } doReturn "OK"
132 * on { buttonPress } doNothing
133 * on { destroy } doAnswer error("Boom!")
134 * }
135 * ```
136 *
137 * __Deprecation note__
138 *
139 * Automatic replacement is not possible due to a change in lambda receiver type to KStubbing<T>
140 *
141 * @param apply builder function to simplify stub configuration by improving type inference.
142 * @see org.mockito.kotlin.mock
143 * @see org.mockito.kotlin.KStubbing.on
144 */
145 @Suppress("DeprecatedCallableAddReplaceWith")
146 @Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING)
147 inline fun <reified T : Any> mock(settings: MockSettings? = null, apply: T.() -> Unit = {}): T =
148 Mockito.mock(T::class.java, settings ?: withSettings()).apply(apply)
149
150 /**
151 * Helper function for stubbing methods without the need to use backticks.
152 *
153 * Avoid. It is preferable to provide stubbing at creation time using the [mock] lambda argument.
154 *
155 * @see org.mockito.kotlin.whenever
156 */
157 @Deprecated(
158 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
159 ReplaceWith(expression = "whenever(methodCall)", imports = ["org.mockito.kotlin.whenever"]),
160 level = WARNING
161 )
whenevernull162 fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)
163
164 /**
165 * __Deprecation note__
166 *
167 * Replace with `KStubbing<T>.on` within [org.mockito.kotlin.mock] { stubbing }
168 *
169 * @see org.mockito.kotlin.mock
170 * @see org.mockito.kotlin.KStubbing.on
171 */
172 @Deprecated(
173 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
174 ReplaceWith(expression = "whenever(mock)", imports = ["org.mockito.kotlin.whenever"]),
175 level = WARNING
176 )
177 fun <T> Stubber.whenever(mock: T): T = `when`(mock)
178
179 /**
180 * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when
181 * kotlin tests are mocking kotlin objects and the methods take non-null parameters:
182 *
183 * java.lang.NullPointerException: capture() must not be null
184 */
185 @Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING)
186 class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) {
187 private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz)
188 fun capture(): T = wrapped.capture()
189 val value: T
190 get() = wrapped.value
191 val allValues: List<T>
192 get() = wrapped.allValues
193 }
194
195 /**
196 * Helper function for creating an argumentCaptor in kotlin.
197 *
198 * Generic T is nullable because implicitly bounded by Any?.
199 *
200 * @see org.mockito.kotlin.argumentCaptor
201 */
202 @Deprecated(
203 "Replace with mockito-kotlin. See http://go/mockito-kotlin",
204 ReplaceWith(expression = "argumentCaptor()", imports = ["org.mockito.kotlin.argumentCaptor"]),
205 level = WARNING
206 )
kotlinArgumentCaptornull207 inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> =
208 KotlinArgumentCaptor(T::class.java)
209
210 /**
211 * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
212 *
213 * val captor = argumentCaptor<Foo>() verify(...).someMethod(captor.capture()) val captured =
214 * captor.value
215 *
216 * becomes:
217 *
218 * val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
219 *
220 * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
221 */
222 // TODO(359670968): rewrite this to use mockito-kotlin
223 inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
224 kotlinArgumentCaptor<T>().apply { block() }.value
225
226 /**
227 * Variant of [withArgCaptor] for capturing multiple arguments.
228 *
229 * val captor = argumentCaptor<Foo>() verify(...).someMethod(captor.capture()) val captured:
230 * List<Foo> = captor.allValues
231 *
232 * becomes:
233 *
234 * val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) }
235 *
236 * @see org.mockito.kotlin.verify
237 */
238 @Suppress("DeprecatedCallableAddReplaceWith")
239 @Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING)
captureManynull240 inline fun <reified T : Any> captureMany(block: KotlinArgumentCaptor<T>.() -> Unit): List<T> =
241 kotlinArgumentCaptor<T>().apply { block() }.allValues
242