• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.launcher3.util
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 org.mockito.ArgumentCaptor
26 import org.mockito.Mockito
27 
28 /**
29  * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when null is
30  * returned.
31  *
32  * Generic T is nullable because implicitly bounded by Any?.
33  */
eqnull34 fun <T> eq(obj: T): T = Mockito.eq<T>(obj)
35 
36 /**
37  * Returns Mockito.same() as nullable type to avoid java.lang.IllegalStateException when null is
38  * returned.
39  *
40  * Generic T is nullable because implicitly bounded by Any?.
41  */
42 fun <T> same(obj: T): T = Mockito.same<T>(obj)
43 
44 /**
45  * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when null is
46  * returned.
47  *
48  * Generic T is nullable because implicitly bounded by Any?.
49  */
50 fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
51 
52 inline fun <reified T> any(): T = any(T::class.java)
53 
54 /** Kotlin type-inferred version of Mockito.nullable() */
55 inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
56 
57 /**
58  * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException when
59  * null is returned.
60  *
61  * Generic T is nullable because implicitly bounded by Any?.
62  */
63 fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
64 
65 /**
66  * Helper function for creating an argumentCaptor in kotlin.
67  *
68  * Generic T is nullable because implicitly bounded by Any?.
69  */
70 inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
71     ArgumentCaptor.forClass(T::class.java)
72 
73 /**
74  * Helper function for creating new mocks, without the need to pass in a [Class] instance.
75  *
76  * Generic T is nullable because implicitly bounded by Any?.
77  */
78 inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)
79 
80 /**
81  * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when
82  * kotlin tests are mocking kotlin objects and the methods take non-null parameters:
83  * ```
84  *     java.lang.NullPointerException: capture() must not be null
85  * ```
86  */
87 class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) {
88     private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz)
89     fun capture(): T = wrapped.capture()
90     val value: T
91         get() = wrapped.value
92 }
93 
94 /**
95  * Helper function for creating an argumentCaptor in kotlin.
96  *
97  * Generic T is nullable because implicitly bounded by Any?.
98  */
kotlinArgumentCaptornull99 inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> =
100     KotlinArgumentCaptor(T::class.java)
101 
102 /**
103  * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
104  *
105  * ```
106  *    val captor = argumentCaptor<Foo>()
107  *    verify(...).someMethod(captor.capture())
108  *    val captured = captor.value
109  * ```
110  *
111  * becomes:
112  * ```
113  *    val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
114  * ```
115  *
116  * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
117  */
118 inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
119     kotlinArgumentCaptor<T>().apply { block() }.value
120