/* * Copyright (C) 2022 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.launcher3.util /** * Kotlin versions of popular mockito methods that can return null in situations when Kotlin expects * a non-null value. Kotlin will throw an IllegalStateException when this takes place ("x must not * be null"). To fix this, we can use methods that modify the return type to be nullable. This * causes Kotlin to skip the null checks. */ import org.mockito.ArgumentCaptor import org.mockito.Mockito /** * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when null is * returned. * * Generic T is nullable because implicitly bounded by Any?. */ fun eq(obj: T): T = Mockito.eq(obj) /** * Returns Mockito.same() as nullable type to avoid java.lang.IllegalStateException when null is * returned. * * Generic T is nullable because implicitly bounded by Any?. */ fun same(obj: T): T = Mockito.same(obj) /** * Returns Mockito.any() as nullable type to avoid java.lang.IllegalStateException when null is * returned. * * Generic T is nullable because implicitly bounded by Any?. */ fun any(type: Class): T = Mockito.any(type) inline fun any(): T = any(T::class.java) /** Kotlin type-inferred version of Mockito.nullable() */ inline fun nullable(): T? = Mockito.nullable(T::class.java) /** * Returns ArgumentCaptor.capture() as nullable type to avoid java.lang.IllegalStateException when * null is returned. * * Generic T is nullable because implicitly bounded by Any?. */ fun capture(argumentCaptor: ArgumentCaptor): T = argumentCaptor.capture() /** * Helper function for creating an argumentCaptor in kotlin. * * Generic T is nullable because implicitly bounded by Any?. */ inline fun argumentCaptor(): ArgumentCaptor = ArgumentCaptor.forClass(T::class.java) /** * Helper function for creating new mocks, without the need to pass in a [Class] instance. * * Generic T is nullable because implicitly bounded by Any?. */ inline fun mock(): T = Mockito.mock(T::class.java) /** * A kotlin implemented wrapper of [ArgumentCaptor] which prevents the following exception when * kotlin tests are mocking kotlin objects and the methods take non-null parameters: * ``` * java.lang.NullPointerException: capture() must not be null * ``` */ class KotlinArgumentCaptor constructor(clazz: Class) { private val wrapped: ArgumentCaptor = ArgumentCaptor.forClass(clazz) fun capture(): T = wrapped.capture() val value: T get() = wrapped.value } /** * Helper function for creating an argumentCaptor in kotlin. * * Generic T is nullable because implicitly bounded by Any?. */ inline fun kotlinArgumentCaptor(): KotlinArgumentCaptor = KotlinArgumentCaptor(T::class.java) /** * Helper function for creating and using a single-use ArgumentCaptor in kotlin. * * ``` * val captor = argumentCaptor() * verify(...).someMethod(captor.capture()) * val captured = captor.value * ``` * * becomes: * ``` * val captured = withArgCaptor { verify(...).someMethod(capture()) } * ``` * * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException. */ inline fun withArgCaptor(block: KotlinArgumentCaptor.() -> Unit): T = kotlinArgumentCaptor().apply { block() }.value