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.intentresolver 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 * Cloned from frameworks/base/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt 25 */ 26 27 import org.mockito.ArgumentCaptor 28 import org.mockito.ArgumentMatcher 29 import org.mockito.ArgumentMatchers 30 import org.mockito.Mockito 31 import org.mockito.stubbing.OngoingStubbing 32 33 /** 34 * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when 35 * null is returned. 36 * 37 * Generic T is nullable because implicitly bounded by Any?. 38 */ eqnull39fun <T> eq(obj: T): T = Mockito.eq<T>(obj) 40 41 /** 42 * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when 43 * null is returned. 44 * 45 * Generic T is nullable because implicitly bounded by Any?. 46 */ 47 fun <T> any(type: Class<T>): T = Mockito.any<T>(type) 48 inline fun <reified T> any(): T = any(T::class.java) 49 50 /** 51 * Returns Mockito.argThat() as nullable type to avoid java.lang.IllegalStateException when 52 * null is returned. 53 * 54 * Generic T is nullable because implicitly bounded by Any?. 55 */ 56 fun <T> argThat(matcher: ArgumentMatcher<T>): T = Mockito.argThat(matcher) 57 58 /** 59 * Kotlin type-inferred version of Mockito.nullable() 60 */ 61 inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java) 62 63 /** 64 * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException 65 * when null is returned. 66 * 67 * Generic T is nullable because implicitly bounded by Any?. 68 */ 69 fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() 70 71 /** 72 * Helper function for creating an argumentCaptor in kotlin. 73 * 74 * Generic T is nullable because implicitly bounded by Any?. 75 */ 76 inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> = 77 ArgumentCaptor.forClass(T::class.java) 78 79 /** 80 * Helper function for creating new mocks, without the need to pass in a [Class] instance. 81 * 82 * Generic T is nullable because implicitly bounded by Any?. 83 * 84 * @param apply builder function to simplify stub configuration by improving type inference. 85 */ 86 inline fun <reified T : Any> mock(apply: T.() -> Unit = {}): T = Mockito.mock(T::class.java) 87 .apply(apply) 88 89 /** 90 * Helper function for stubbing methods without the need to use backticks. 91 * 92 * @see Mockito.when 93 */ whenevernull94fun <T> whenever(methodCall: T): OngoingStubbing<T> = Mockito.`when`(methodCall) 95 96 /** 97 * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when 98 * kotlin tests are mocking kotlin objects and the methods take non-null parameters: 99 * 100 * java.lang.NullPointerException: capture() must not be null 101 */ 102 class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) { 103 private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz) 104 fun capture(): T = wrapped.capture() 105 val value: T 106 get() = wrapped.value 107 val allValues: List<T> 108 get() = wrapped.allValues 109 } 110 111 /** 112 * Helper function for creating an argumentCaptor in kotlin. 113 * 114 * Generic T is nullable because implicitly bounded by Any?. 115 */ kotlinArgumentCaptornull116inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> = 117 KotlinArgumentCaptor(T::class.java) 118 119 /** 120 * Helper function for creating and using a single-use ArgumentCaptor in kotlin. 121 * 122 * val captor = argumentCaptor<Foo>() 123 * verify(...).someMethod(captor.capture()) 124 * val captured = captor.value 125 * 126 * becomes: 127 * 128 * val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) } 129 * 130 * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException. 131 */ 132 inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T = 133 kotlinArgumentCaptor<T>().apply { block() }.value 134 135 /** 136 * Variant of [withArgCaptor] for capturing multiple arguments. 137 * 138 * val captor = argumentCaptor<Foo>() 139 * verify(...).someMethod(captor.capture()) 140 * val captured: List<Foo> = captor.allValues 141 * 142 * becomes: 143 * 144 * val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) } 145 */ captureManynull146inline fun <reified T : Any> captureMany(block: KotlinArgumentCaptor<T>.() -> Unit): List<T> = 147 kotlinArgumentCaptor<T>().apply{ block() }.allValues 148 <lambda>null149inline fun <reified T> anyOrNull() = ArgumentMatchers.argThat(ArgumentMatcher<T?> { true }) 150