xref: /aosp_15_r20/frameworks/base/libs/dream/lowlight/tests/src/com/android/dream/lowlight/utils/KotlinMockitoHelpers.kt (revision d57664e9bc4670b3ecf6748a746a57c557b6bc9e)
1 package src.com.android.dream.lowlight.utils
2 
3 import org.mockito.ArgumentCaptor
4 import org.mockito.ArgumentMatcher
5 import org.mockito.Mockito
6 import org.mockito.Mockito.`when`
7 import org.mockito.stubbing.OngoingStubbing
8 import org.mockito.stubbing.Stubber
9 
10 /**
11  * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when
12  * null is returned.
13  *
14  * Generic T is nullable because implicitly bounded by Any?.
15  */
eqnull16 fun <T> eq(obj: T): T = Mockito.eq<T>(obj)
17 
18 /**
19  * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when
20  * null is returned.
21  *
22  * Generic T is nullable because implicitly bounded by Any?.
23  */
24 fun <T> any(type: Class<T>): T = Mockito.any<T>(type)
25 inline fun <reified T> any(): T = any(T::class.java)
26 
27 /**
28  * Returns Mockito.argThat() as nullable type to avoid java.lang.IllegalStateException when
29  * null is returned.
30  *
31  * Generic T is nullable because implicitly bounded by Any?.
32  */
33 fun <T> argThat(matcher: ArgumentMatcher<T>): T = Mockito.argThat(matcher)
34 
35 /**
36  * Kotlin type-inferred version of Mockito.nullable()
37  */
38 inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java)
39 
40 /**
41  * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException
42  * when null is returned.
43  *
44  * Generic T is nullable because implicitly bounded by Any?.
45  */
46 fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture()
47 
48 /**
49  * Helper function for creating an argumentCaptor in kotlin.
50  *
51  * Generic T is nullable because implicitly bounded by Any?.
52  */
53 inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
54     ArgumentCaptor.forClass(T::class.java)
55 
56 /**
57  * Helper function for creating new mocks, without the need to pass in a [Class] instance.
58  *
59  * Generic T is nullable because implicitly bounded by Any?.
60  *
61  * @param apply builder function to simplify stub configuration by improving type inference.
62  */
63 inline fun <reified T : Any> mock(apply: T.() -> Unit = {}): T = Mockito.mock(T::class.java)
64     .apply(apply)
65 
66 /**
67  * Helper function for stubbing methods without the need to use backticks.
68  *
69  * @see Mockito.when
70  */
whenevernull71 fun <T> whenever(methodCall: T): OngoingStubbing<T> = `when`(methodCall)
72 fun <T> Stubber.whenever(mock: T): T = `when`(mock)
73 
74 /**
75  * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when
76  * kotlin tests are mocking kotlin objects and the methods take non-null parameters:
77  *
78  *     java.lang.NullPointerException: capture() must not be null
79  */
80 class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) {
81     private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz)
82     fun capture(): T = wrapped.capture()
83     val value: T
84         get() = wrapped.value
85     val allValues: List<T>
86         get() = wrapped.allValues
87 }
88 
89 /**
90  * Helper function for creating an argumentCaptor in kotlin.
91  *
92  * Generic T is nullable because implicitly bounded by Any?.
93  */
kotlinArgumentCaptornull94 inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> =
95     KotlinArgumentCaptor(T::class.java)
96 
97 /**
98  * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
99  *
100  *    val captor = argumentCaptor<Foo>()
101  *    verify(...).someMethod(captor.capture())
102  *    val captured = captor.value
103  *
104  * becomes:
105  *
106  *    val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
107  *
108  * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException.
109  */
110 inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T =
111     kotlinArgumentCaptor<T>().apply { block() }.value
112 
113 /**
114  * Variant of [withArgCaptor] for capturing multiple arguments.
115  *
116  *    val captor = argumentCaptor<Foo>()
117  *    verify(...).someMethod(captor.capture())
118  *    val captured: List<Foo> = captor.allValues
119  *
120  * becomes:
121  *
122  *    val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) }
123  */
captureManynull124 inline fun <reified T : Any> captureMany(block: KotlinArgumentCaptor<T>.() -> Unit): List<T> =
125     kotlinArgumentCaptor<T>().apply{ block() }.allValues
126