1 /*
2  * Copyright 2024 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.photopicker.tests.utils.mockito
18 
19 import android.content.Context
20 import org.mockito.ArgumentCaptor
21 import org.mockito.ArgumentMatchers
22 import org.mockito.Mockito
23 import org.mockito.invocation.InvocationOnMock
24 
25 /**
26  * Wrapper around Mockito's when method. "when" is a protected keyword in Kotlin, so this provides a
27  * convenient wrapper to use.
28  */
whenevernull29 fun <Type> whenever(mock: Type) = Mockito.`when`(mock)
30 
31 /**
32  * Wrapper around Mockito's when method. "when" is a protected keyword in Kotlin, so this provides a
33  * convenient wrapper to use that also includes a block for creating a .thenAnswer chained call.
34  */
35 fun <Type> whenever(mock: Type, block: InvocationOnMock.() -> Type) =
36     Mockito.`when`(mock).thenAnswer { block(it) }
37 
38 /**
39  * Returns ArgumentCaptor.capture() as nullable type to avoid [java.lang.IllegalStateException] when
40  * null is returned.
41  *
42  * Generic T is nullable because implicitly bounded by Any?.
43  */
capturenull44 fun <Type> capture(argumentCaptor: ArgumentCaptor<Type>): Type = argumentCaptor.capture()
45 
46 /**
47  * Registers mock returns for the designated system service. This is a Mockito helper to help with
48  * the [requireSystemService] extension for correctly mocking out services based on their type
49  * signatures.
50  *
51  * @param context The (mock) context object to stub out service on.
52  * @param classToMock The java class of the system service to be mocked.
53  * @param block A block that returns the mocked service value.
54  */
55 fun <Type> mockSystemService(
56     context: Context,
57     classToMock: Class<Type>,
58     block: InvocationOnMock.() -> Type
59 ) {
60     whenever(context.getSystemServiceName(classToMock)) { classToMock.simpleName }
61     whenever(context.getSystemService(classToMock.simpleName)) { block() }
62 }
63 
64 /**
65  * We can't use [org.mockito.ArgumentMatchers.eq] method directly for non-nullable Kotlin objects.
66  * This utility method checks for nullability of the result [org.mockito.ArgumentMatchers.eq] and
67  * returns the same value if found to be null.
68  *
69  * @param value The value that you wish to pass to eq
70  */
nonNullableEqnull71 fun <Type> nonNullableEq(value: Type): Type {
72     return ArgumentMatchers.eq(value) ?: value
73 }
74 
75 /**
76  * We can't use [org.mockito.ArgumentMatchers.any] method directly for non-nullable Kotlin objects.
77  * This utility method checks for nullability of the result [org.mockito.ArgumentMatchers.eq] and
78  * returns the same value if found to be null.
79  *
80  * @param typeClass The java class of the type that should match [org.mockito.ArgumentMatchers.any]
81  * @param defaultValue a non-null instance of the type [typeClass]
82  */
nonNullableAnynull83 fun <Type> nonNullableAny(typeClass: Class<Type>, defaultValue: Type): Type {
84     return ArgumentMatchers.any(typeClass) ?: defaultValue
85 }
86