diff options
Diffstat (limited to 'tests')
11 files changed, 604 insertions, 458 deletions
diff --git a/tests/shared/src/com/android/intentresolver/FrameworkMocksKosmos.kt b/tests/shared/src/com/android/intentresolver/FrameworkMocksKosmos.kt index d578fb66..df3931c6 100644 --- a/tests/shared/src/com/android/intentresolver/FrameworkMocksKosmos.kt +++ b/tests/shared/src/com/android/intentresolver/FrameworkMocksKosmos.kt @@ -20,6 +20,6 @@ import android.content.ContentResolver import android.content.pm.PackageManager import com.android.systemui.kosmos.Kosmos -var Kosmos.contentResolver by Kosmos.Fixture { mock<ContentResolver> {} } +var Kosmos.contentResolver by Kosmos.Fixture { org.mockito.kotlin.mock<ContentResolver> {} } var Kosmos.contentInterface by Kosmos.Fixture { contentResolver } -var Kosmos.packageManager by Kosmos.Fixture { mock<PackageManager> {} } +var Kosmos.packageManager by Kosmos.Fixture { org.mockito.kotlin.mock<PackageManager> {} } diff --git a/tests/shared/src/com/android/intentresolver/MockitoKotlinHelpers.kt b/tests/shared/src/com/android/intentresolver/MockitoKotlinHelpers.kt index b7b97d6f..40ee6325 100644 --- a/tests/shared/src/com/android/intentresolver/MockitoKotlinHelpers.kt +++ b/tests/shared/src/com/android/intentresolver/MockitoKotlinHelpers.kt @@ -18,13 +18,7 @@ package com.android.intentresolver -/** - * 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. Cloned from - * frameworks/base/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt - */ +import kotlin.DeprecationLevel.WARNING import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatcher import org.mockito.ArgumentMatchers @@ -34,12 +28,25 @@ import org.mockito.stubbing.Answer import org.mockito.stubbing.OngoingStubbing import org.mockito.stubbing.Stubber +/* + * 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. Cloned from + * frameworks/base/packages/SystemUI/tests/utils/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt + */ + /** * Returns Mockito.eq() as nullable type to avoid java.lang.IllegalStateException when null is * returned. * * Generic T is nullable because implicitly bounded by Any?. */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "eq", imports = ["org.mockito.kotlin.eq"]), + level = WARNING +) inline fun <T> eq(obj: T): T = Mockito.eq<T>(obj) ?: obj /** @@ -48,6 +55,11 @@ inline fun <T> eq(obj: T): T = Mockito.eq<T>(obj) ?: obj * * Generic T is nullable because implicitly bounded by Any?. */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "same(obj)", imports = ["org.mockito.kotlin.same"]), + level = WARNING +) inline fun <T> same(obj: T): T = Mockito.same<T>(obj) ?: obj /** @@ -56,8 +68,18 @@ inline fun <T> same(obj: T): T = Mockito.same<T>(obj) ?: obj * * Generic T is nullable because implicitly bounded by Any?. */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "any(type)", imports = ["org.mockito.kotlin.any"]), + level = WARNING +) inline fun <T> any(type: Class<T>): T = Mockito.any<T>(type) +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "any()", imports = ["org.mockito.kotlin.any"]), + level = WARNING +) inline fun <reified T> any(): T = any(T::class.java) /** @@ -66,9 +88,23 @@ inline fun <reified T> any(): T = any(T::class.java) * * Generic T is nullable because implicitly bounded by Any?. */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "argThat(matcher)", imports = ["org.mockito.kotlin.argThat"]), + level = WARNING +) inline fun <T> argThat(matcher: ArgumentMatcher<T>): T = Mockito.argThat(matcher) -/** Kotlin type-inferred version of Mockito.nullable() */ +/** + * Kotlin type-inferred version of Mockito.nullable() + * + * @see org.mockito.kotlin.anyOrNull + */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "anyOrNull()", imports = ["org.mockito.kotlin.anyOrNull"]), + level = WARNING +) inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java) /** @@ -76,14 +112,28 @@ inline fun <reified T> nullable(): T? = Mockito.nullable(T::class.java) * null is returned. * * Generic T is nullable because implicitly bounded by Any?. + * + * @see org.mockito.kotlin.capture */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "capture(argumentCaptor)", imports = ["org.mockito.kotlin.capture"]), + level = WARNING +) inline fun <T> capture(argumentCaptor: ArgumentCaptor<T>): T = argumentCaptor.capture() /** * Helper function for creating an argumentCaptor in kotlin. * * Generic T is nullable because implicitly bounded by Any?. + * + * @see org.mockito.kotlin.argumentCaptor */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "argumentCaptor()", imports = ["org.mockito.kotlin.argumentCaptor"]), + level = WARNING +) inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> = ArgumentCaptor.forClass(T::class.java) @@ -92,24 +142,68 @@ inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> = * * Generic T is nullable because implicitly bounded by Any?. * - * @param apply builder function to simplify stub configuration by improving type inference. + * Updated kotlin-mockito usage: + * ``` + * val value: Widget = mock<> { + * on { status } doReturn "OK" + * on { buttonPress } doNothing + * on { destroy } doAnswer error("Boom!") + * } + * ``` + * + * __Deprecation note__ + * + * Automatic replacement is not possible due to a change in lambda receiver type to KStubbing<T> + * + * @see org.mockito.kotlin.mock + * @see org.mockito.kotlin.KStubbing.on */ +@Suppress("DeprecatedCallableAddReplaceWith") +@Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING) inline fun <reified T : Any> mock( mockSettings: MockSettings = Mockito.withSettings(), apply: T.() -> Unit = {} ): T = Mockito.mock(T::class.java, mockSettings).apply(apply) /** Matches any array of type T. */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "anyArray()", imports = ["org.mockito.kotlin.anyArray"]), + level = WARNING +) inline fun <reified T : Any?> anyArray(): Array<T> = Mockito.any(Array<T>::class.java) ?: arrayOf() /** * Helper function for stubbing methods without the need to use backticks. * - * @see Mockito.when + * Avoid. It is preferable to provide stubbing at creation time using the [mock] lambda argument. + * + * @see org.mockito.kotlin.whenever */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "whenever(methodCall)", imports = ["org.mockito.kotlin.whenever"]), + level = WARNING +) inline fun <T> whenever(methodCall: T): OngoingStubbing<T> = Mockito.`when`(methodCall) -/** Helper function for stubbing methods without the need to use backticks. */ +/** + * Helper function for stubbing methods without the need to use backticks. + * + * Avoid. It is preferable to provide stubbing at creation time using the [mock] lambda argument. + * + * __Deprecation note__ + * + * Replace with KStubber<T>.on within [org.mockito.kotlin.mock] { stubbing } + * + * @see org.mockito.kotlin.mock + * @see org.mockito.kotlin.KStubbing.on + */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "whenever(mock)", imports = ["org.mockito.kotlin.whenever"]), + level = WARNING +) inline fun <T> Stubber.whenever(mock: T): T = `when`(mock) /** @@ -118,6 +212,7 @@ inline fun <T> Stubber.whenever(mock: T): T = `when`(mock) * * java.lang.NullPointerException: capture() must not be null */ +@Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING) class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) { private val wrapped: ArgumentCaptor<T> = ArgumentCaptor.forClass(clazz) fun capture(): T = wrapped.capture() @@ -131,7 +226,14 @@ class KotlinArgumentCaptor<T> constructor(clazz: Class<T>) { * Helper function for creating an argumentCaptor in kotlin. * * Generic T is nullable because implicitly bounded by Any?. + * + * @see org.mockito.kotlin.argumentCaptor */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "argumentCaptor()", imports = ["org.mockito.kotlin.argumentCaptor"]), + level = WARNING +) inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> = KotlinArgumentCaptor(T::class.java) @@ -146,7 +248,11 @@ inline fun <reified T : Any> kotlinArgumentCaptor(): KotlinArgumentCaptor<T> = * val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) } * * NOTE: this uses the KotlinArgumentCaptor to avoid the NullPointerException. + * + * @see org.mockito.kotlin.verify */ +@Suppress("DeprecatedCallableAddReplaceWith") +@Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING) inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> Unit): T = kotlinArgumentCaptor<T>().apply { block() }.value @@ -159,27 +265,28 @@ inline fun <reified T : Any> withArgCaptor(block: KotlinArgumentCaptor<T>.() -> * becomes: * * val capturedList = captureMany<Foo> { verify(...).someMethod(capture()) } + * + * @see org.mockito.kotlin.verify */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "capture()", imports = ["org.mockito.kotlin.capture"]), + level = WARNING +) inline fun <reified T : Any> captureMany(block: KotlinArgumentCaptor<T>.() -> Unit): List<T> = kotlinArgumentCaptor<T>().apply { block() }.allValues +/** @see org.mockito.kotlin.anyOrNull */ +@Deprecated( + "Replace with mockito-kotlin. See http://go/mockito-kotlin", + ReplaceWith(expression = "anyOrNull()", imports = ["org.mockito.kotlin.anyOrNull"]), + level = WARNING +) inline fun <reified T> anyOrNull() = ArgumentMatchers.argThat(ArgumentMatcher<T?> { true }) /** - * Intended as a default Answer for a mock to prevent dependence on defaults. - * - * Use as: - * ``` - * val context = mock<Context>(withSettings() - * .defaultAnswer(THROWS_EXCEPTION)) - * ``` - * - * To avoid triggering the exception during stubbing, must ONLY use one of the doXXX() methods, such - * as: - * * [doAnswer][Mockito.doAnswer] - * * [doCallRealMethod][Mockito.doCallRealMethod] - * * [doNothing][Mockito.doNothing] - * * [doReturn][Mockito.doReturn] - * * [doThrow][Mockito.doThrow] + * @see org.mockito.kotlin.mock + * @see org.mockito.kotlin.doThrow */ +@Deprecated("Replace with mockito-kotlin. See http://go/mockito-kotlin", level = WARNING) val THROWS_EXCEPTION = Answer { error("Unstubbed behavior was accessed.") } diff --git a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/PendingIntentSenderKosmos.kt b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/PendingIntentSenderKosmos.kt index f022373d..1b4c0c8f 100644 --- a/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/PendingIntentSenderKosmos.kt +++ b/tests/shared/src/com/android/intentresolver/contentpreview/payloadtoggle/domain/intent/PendingIntentSenderKosmos.kt @@ -16,7 +16,7 @@ package com.android.intentresolver.contentpreview.payloadtoggle.domain.intent -import com.android.intentresolver.mock import com.android.systemui.kosmos.Kosmos +import org.mockito.kotlin.mock var Kosmos.pendingIntentSender by Kosmos.Fixture { mock<PendingIntentSender> {} } diff --git a/tests/shared/src/com/android/intentresolver/platform/FakeUserManager.kt b/tests/shared/src/com/android/intentresolver/platform/FakeUserManager.kt index ff1e84bd..32cb9062 100644 --- a/tests/shared/src/com/android/intentresolver/platform/FakeUserManager.kt +++ b/tests/shared/src/com/android/intentresolver/platform/FakeUserManager.kt @@ -26,22 +26,18 @@ import android.os.IUserManager import android.os.UserHandle import android.os.UserManager import androidx.annotation.NonNull -import com.android.intentresolver.THROWS_EXCEPTION import com.android.intentresolver.data.repository.AvailabilityChange import com.android.intentresolver.data.repository.ProfileAdded import com.android.intentresolver.data.repository.ProfileRemoved import com.android.intentresolver.data.repository.UserEvent -import com.android.intentresolver.mock import com.android.intentresolver.platform.FakeUserManager.State -import com.android.intentresolver.whenever import kotlin.random.Random import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.consumeAsFlow -import org.mockito.Mockito.RETURNS_SELF -import org.mockito.Mockito.doAnswer -import org.mockito.Mockito.doReturn -import org.mockito.Mockito.withSettings +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.whenever /** * A stand-in for [UserManager] to support testing of data layer components which depend on it. @@ -211,11 +207,16 @@ class FakeUserManager(val state: State = State()) : } /** A safe mock of [Context] which throws on any unstubbed method call. */ -private fun mockContext(user: UserHandle = UserHandle.SYSTEM): Context { - return mock<Context>(withSettings().defaultAnswer(THROWS_EXCEPTION)) { - doAnswer(RETURNS_SELF).whenever(this).applicationContext - doReturn(user).whenever(this).user - doReturn(user.identifier).whenever(this).userId +private fun mockContext(userHandle: UserHandle = UserHandle.SYSTEM): Context { + return mock<Context>( + defaultAnswer = { + error("Unstubbed behavior invoked! (${it.method}(${it.arguments.asList()})") + } + ) { + // Careful! Specify behaviors *first* to avoid throwing while stubbing! + doReturn(mock).whenever(mock).applicationContext + doReturn(userHandle).whenever(mock).user + doReturn(userHandle.identifier).whenever(mock).userId } } @@ -229,7 +230,11 @@ private fun FakeUserManager.ProfileType.toUserType(): String { /** A safe mock of [IUserManager] which throws on any unstubbed method call. */ fun mockService(): IUserManager { - return mock<IUserManager>(withSettings().defaultAnswer(THROWS_EXCEPTION)) + return mock<IUserManager>( + defaultAnswer = { + error("Unstubbed behavior invoked! ${it.method}(${it.arguments.asList()}") + } + ) } val UserInfo.debugString: String diff --git a/tests/unit/src/com/android/intentresolver/EnterTransitionAnimationDelegateTest.kt b/tests/unit/src/com/android/intentresolver/EnterTransitionAnimationDelegateTest.kt index c7d20000..2b7d6ff9 100644 --- a/tests/unit/src/com/android/intentresolver/EnterTransitionAnimationDelegateTest.kt +++ b/tests/unit/src/com/android/intentresolver/EnterTransitionAnimationDelegateTest.kt @@ -31,10 +31,11 @@ import kotlinx.coroutines.test.setMain import org.junit.After import org.junit.Before import org.junit.Test -import org.mockito.Mockito.anyInt -import org.mockito.Mockito.never -import org.mockito.Mockito.times -import org.mockito.Mockito.verify +import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock +import org.mockito.kotlin.times +import org.mockito.kotlin.verify private const val TIMEOUT_MS = 200 @@ -48,18 +49,18 @@ class EnterTransitionAnimationDelegateTest { private val transitionTargetView = mock<View> { // avoid the request-layout path in the delegate - whenever(isInLayout).thenReturn(true) + on { isInLayout } doReturn true } private val windowMock = mock<Window>() private val resourcesMock = - mock<Resources> { whenever(getInteger(anyInt())).thenReturn(TIMEOUT_MS) } + mock<Resources> { on { getInteger(any<Int>()) } doReturn TIMEOUT_MS } private val activity = mock<ComponentActivity> { - whenever(lifecycle).thenReturn(lifecycleOwner.lifecycle) - whenever(resources).thenReturn(resourcesMock) - whenever(isActivityTransitionRunning).thenReturn(true) - whenever(window).thenReturn(windowMock) + on { lifecycle } doReturn lifecycleOwner.lifecycle + on { resources } doReturn resourcesMock + on { isActivityTransitionRunning } doReturn true + on { window } doReturn windowMock } private val testSubject = EnterTransitionAnimationDelegate(activity) { transitionTargetView } @@ -82,8 +83,8 @@ class EnterTransitionAnimationDelegateTest { testSubject.markOffsetCalculated() scheduler.advanceTimeBy(TIMEOUT_MS + 1L) - verify(activity, times(1)).startPostponedEnterTransition() - verify(windowMock, never()).setWindowAnimations(anyInt()) + verify(activity) { 1 * { mock.startPostponedEnterTransition() } } + verify(windowMock) { 0 * { setWindowAnimations(any<Int>()) } } } @Test @@ -101,12 +102,12 @@ class EnterTransitionAnimationDelegateTest { @Test fun test_postponeTransition_resume_animation_conditions() { testSubject.postponeTransition() - verify(activity, never()).startPostponedEnterTransition() + verify(activity) { 0 * { startPostponedEnterTransition() } } testSubject.markOffsetCalculated() - verify(activity, never()).startPostponedEnterTransition() + verify(activity) { 0 * { startPostponedEnterTransition() } } testSubject.onAllTransitionElementsReady() - verify(activity, times(1)).startPostponedEnterTransition() + verify(activity) { 1 * { startPostponedEnterTransition() } } } } diff --git a/tests/unit/src/com/android/intentresolver/ResolverListAdapterTest.kt b/tests/unit/src/com/android/intentresolver/ResolverListAdapterTest.kt index 2953a650..d8cb7adc 100644 --- a/tests/unit/src/com/android/intentresolver/ResolverListAdapterTest.kt +++ b/tests/unit/src/com/android/intentresolver/ResolverListAdapterTest.kt @@ -29,11 +29,17 @@ import com.android.intentresolver.ResolverListAdapter.ResolverListCommunicator import com.android.intentresolver.icons.TargetDataLoader import com.android.intentresolver.util.TestExecutor import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage import org.junit.Test -import org.mockito.Mockito.anyBoolean -import org.mockito.Mockito.inOrder -import org.mockito.Mockito.never -import org.mockito.Mockito.verify +import org.mockito.kotlin.any +import org.mockito.kotlin.doAnswer +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.eq +import org.mockito.kotlin.inOrder +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify +import org.mockito.kotlin.whenever private const val PKG_NAME = "org.pkg.app" private const val PKG_NAME_TWO = "org.pkg.two.app" @@ -43,20 +49,15 @@ private const val CLASS_NAME = "org.pkg.app.TheClass" class ResolverListAdapterTest { private val layoutInflater = mock<LayoutInflater>() private val packageManager = mock<PackageManager>() - private val userManager = mock<UserManager> { whenever(isManagedProfile).thenReturn(false) } + private val userManager = mock<UserManager> { on { isManagedProfile } doReturn (false) } private val context = mock<Context> { - whenever(getSystemService(Context.LAYOUT_INFLATER_SERVICE)).thenReturn(layoutInflater) - whenever(getSystemService(Context.USER_SERVICE)).thenReturn(userManager) - whenever(packageManager).thenReturn(this@ResolverListAdapterTest.packageManager) + on { getSystemService(Context.LAYOUT_INFLATER_SERVICE) } doReturn layoutInflater + on { getSystemService(Context.USER_SERVICE) } doReturn userManager + on { packageManager } doReturn this@ResolverListAdapterTest.packageManager } private val targetIntent = Intent(Intent.ACTION_SEND) private val payloadIntents = listOf(targetIntent) - private val resolverListController = - mock<ResolverListController> { - whenever(filterIneligibleActivities(any(), anyBoolean())).thenReturn(null) - whenever(filterLowPriority(any(), anyBoolean())).thenReturn(null) - } private val resolverListCommunicator = FakeResolverListCommunicator() private val userHandle = UserHandle.of(UserHandle.USER_CURRENT) private val targetDataLoader = mock<TargetDataLoader>() @@ -66,16 +67,20 @@ class ResolverListAdapterTest { @Test fun test_oneTargetNoLastChosen_oneTargetInAdapter() { val resolvedTargets = createResolvedComponents(ComponentName(PKG_NAME, CLASS_NAME)) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + } val testSubject = ResolverListAdapter( context, @@ -111,18 +116,21 @@ class ResolverListAdapterTest { @Test fun test_oneTargetThatWasLastChosen_NoTargetsInAdapter() { val resolvedTargets = createResolvedComponents(ComponentName(PKG_NAME, CLASS_NAME)) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) - whenever(resolverListController.lastChosen) - .thenReturn(resolvedTargets[0].getResolveInfoAt(0)) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { lastChosen } doReturn resolvedTargets[0].getResolveInfoAt(0) + } val testSubject = ResolverListAdapter( context, @@ -157,18 +165,21 @@ class ResolverListAdapterTest { @Test fun test_oneTargetLastChosenNotInTheList_oneTargetInAdapter() { val resolvedTargets = createResolvedComponents(ComponentName(PKG_NAME, CLASS_NAME)) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) - whenever(resolverListController.lastChosen) - .thenReturn(createResolveInfo(PKG_NAME_TWO, CLASS_NAME)) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { lastChosen } doReturn createResolveInfo(PKG_NAME_TWO, CLASS_NAME, userHandle) + } val testSubject = ResolverListAdapter( context, @@ -195,7 +206,9 @@ class ResolverListAdapterTest { assertThat(testSubject.hasFilteredItem()).isTrue() assertThat(testSubject.filteredItem).isNull() assertThat(testSubject.filteredPosition).isLessThan(0) - assertThat(testSubject.unfilteredResolveList).containsExactlyElementsIn(resolvedTargets) + assertWithMessage("unfilteredResolveList") + .that(testSubject.unfilteredResolveList) + .containsExactlyElementsIn(resolvedTargets) assertThat(testSubject.isTabLoaded).isTrue() assertThat(backgroundExecutor.pendingCommandCount).isEqualTo(0) } @@ -203,18 +216,21 @@ class ResolverListAdapterTest { @Test fun test_oneTargetThatWasLastChosenFilteringDisabled_oneTargetInAdapter() { val resolvedTargets = createResolvedComponents(ComponentName(PKG_NAME, CLASS_NAME)) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) - whenever(resolverListController.lastChosen) - .thenReturn(resolvedTargets[0].getResolveInfoAt(0)) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { lastChosen } doReturn resolvedTargets[0].getResolveInfoAt(0) + } val testSubject = ResolverListAdapter( context, @@ -242,7 +258,9 @@ class ResolverListAdapterTest { assertThat(testSubject.hasFilteredItem()).isFalse() assertThat(testSubject.filteredItem).isNull() assertThat(testSubject.filteredPosition).isLessThan(0) - assertThat(testSubject.unfilteredResolveList).containsExactlyElementsIn(resolvedTargets) + assertWithMessage("unfilteredResolveList") + .that(testSubject.unfilteredResolveList) + .containsExactlyElementsIn(resolvedTargets) assertThat(testSubject.isTabLoaded).isTrue() } @@ -272,20 +290,23 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - if (hasLastChosen) { - whenever(resolverListController.lastChosen) - .thenReturn(resolvedTargets[0].getResolveInfoAt(0)) - } - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + if (hasLastChosen) { + on { lastChosen } doReturn resolvedTargets[0].getResolveInfoAt(0) + } + } val resolverListCommunicator = FakeResolverListCommunicator(useLayoutWithDefaults) val testSubject = ResolverListAdapter( @@ -346,18 +367,21 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - whenever(resolverListController.lastChosen) - .thenReturn(createResolveInfo(PKG_NAME, CLASS_NAME + "2")) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { lastChosen } doReturn createResolveInfo(PKG_NAME, CLASS_NAME + "2", userHandle) + } val testSubject = ResolverListAdapter( context, @@ -410,19 +434,22 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME_TWO, CLASS_NAME), ) resolvedTargets[1].getResolveInfoAt(0).targetUserId = 10 - whenever(resolvedTargets[1].getResolveInfoAt(0).loadLabel(any())).thenReturn("Label") - whenever(resolverListController.lastChosen) - .thenReturn(resolvedTargets[0].getResolveInfoAt(0)) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) + // whenever(resolvedTargets[1].getResolveInfoAt(0).loadLabel(any())).thenReturn("Label") + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { lastChosen } doReturn resolvedTargets[0].getResolveInfoAt(0) + } val testSubject = ResolverListAdapter( context, @@ -463,21 +490,26 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) - whenever(resolverListController.sort(any())).thenAnswer { invocation -> - val components = invocation.arguments[0] as MutableList<ResolvedComponentInfo> - components[0] = components[1].also { components[1] = components[0] } - null - } + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { sort(any()) } doAnswer + { + val components = it.arguments[0] as MutableList<ResolvedComponentInfo> + components[0] = components[1].also { components[1] = components[0] } + null + } + } val testSubject = ResolverListAdapter( context, @@ -516,22 +548,26 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) - whenever(resolverListController.filterIneligibleActivities(any(), anyBoolean())) - .thenAnswer { invocation -> - val components = invocation.arguments[0] as MutableList<ResolvedComponentInfo> - val original = ArrayList(components) - components.removeAt(1) - original + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { filterIneligibleActivities(any(), any()) } doAnswer + { + val components = it.arguments[0] as MutableList<ResolvedComponentInfo> + val original = ArrayList(components) + components.removeAt(1) + original + } } val testSubject = ResolverListAdapter( @@ -565,24 +601,28 @@ class ResolverListAdapterTest { @Suppress("UNCHECKED_CAST") @Test fun test_baseResolveList_excludedFromIneligibleActivityFiltering() { - val rList = listOf(createResolveInfo(PKG_NAME, CLASS_NAME)) - whenever(resolverListController.addResolveListDedupe(any(), eq(targetIntent), eq(rList))) - .thenAnswer { invocation -> - val result = invocation.arguments[0] as MutableList<ResolvedComponentInfo> - result.addAll( - createResolvedComponents( - ComponentName(PKG_NAME, CLASS_NAME), - ComponentName(PKG_NAME_TWO, CLASS_NAME), - ) - ) - null - } - whenever(resolverListController.filterIneligibleActivities(any(), anyBoolean())) - .thenAnswer { invocation -> - val components = invocation.arguments[0] as MutableList<ResolvedComponentInfo> - val original = ArrayList(components) - components.clear() - original + val rList = listOf(createResolveInfo(PKG_NAME, CLASS_NAME, userHandle)) + val resolverListController = + mock<ResolverListController> { + on { filterLowPriority(any(), any()) } doReturn null + on { addResolveListDedupe(any(), eq(targetIntent), eq(rList)) } doAnswer + { + val result = it.arguments[0] as MutableList<ResolvedComponentInfo> + result.addAll( + createResolvedComponents( + ComponentName(PKG_NAME, CLASS_NAME), + ComponentName(PKG_NAME_TWO, CLASS_NAME), + ) + ) + null + } + on { filterIneligibleActivities(any(), any()) } doAnswer + { + val components = it.arguments[0] as MutableList<ResolvedComponentInfo> + val original = ArrayList(components) + components.clear() + original + } } val testSubject = ResolverListAdapter( @@ -619,23 +659,26 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) - whenever(resolverListController.filterLowPriority(any(), anyBoolean())).thenAnswer { - invocation -> - val components = invocation.arguments[0] as MutableList<ResolvedComponentInfo> - val original = ArrayList(components) - components.removeAt(1) - original - } + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + on { filterLowPriority(any(), any()) } doAnswer + { + val components = it.arguments[0] as MutableList<ResolvedComponentInfo> + val original = ArrayList(components) + components.removeAt(1) + original + } + } val testSubject = ResolverListAdapter( context, @@ -672,19 +715,23 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) val initialComponent = ComponentName(PKG_NAME_THREE, CLASS_NAME) val initialIntents = arrayOf(Intent(Intent.ACTION_SEND).apply { component = initialComponent }) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + } whenever(packageManager.getActivityInfo(eq(initialComponent), eq(0))) .thenReturn(createActivityInfo(initialComponent)) val testSubject = @@ -742,16 +789,20 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - whenever( - resolverListController.getResolversForIntentAsUser( - true, - resolverListCommunicator.shouldGetActivityMetadata(), - resolverListCommunicator.shouldGetOnlyDefaultActivities(), - payloadIntents, - userHandle - ) - ) - .thenReturn(resolvedTargets) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { + getResolversForIntentAsUser( + true, + resolverListCommunicator.shouldGetActivityMetadata(), + resolverListCommunicator.shouldGetOnlyDefaultActivities(), + payloadIntents, + userHandle + ) + } doReturn resolvedTargets + } val initialComponent = ComponentName(PKG_NAME_TWO, CLASS_NAME) val initialIntents = arrayOf(Intent(Intent.ACTION_SEND).apply { component = initialComponent }) @@ -808,6 +859,7 @@ class ResolverListAdapterTest { @Test fun testPostListReadyAtEndOfRebuild_synchronous() { val communicator = mock<ResolverListCommunicator> {} + val resolverListController = mock<ResolverListController>() val testSubject = ResolverListAdapter( context, @@ -839,26 +891,16 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - // TODO: there's a lot of boilerplate required for this test even to trigger the expected - // conditions; if the configuration is incorrect, the test may accidentally pass for the - // wrong reasons. Separating responsibilities to other components will help minimize the - // *amount* of boilerplate, but we should also consider setting up test defaults that work - // according to our usual expectations so that we don't overlook false-negative results. - whenever( - resolverListController.getResolversForIntentAsUser( - any(), - any(), - any(), - any(), - any(), - ) - ) - .thenReturn(resolvedTargets) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { getResolversForIntentAsUser(any(), any(), any(), any(), any()) } doReturn + resolvedTargets + } val communicator = mock<ResolverListCommunicator> { - whenever(getReplacementIntent(any(), any())).thenAnswer { invocation -> - invocation.arguments[1] - } + on { getReplacementIntent(any(), any()) } doAnswer { it.arguments[1] as Intent } } val testSubject = ResolverListAdapter( @@ -897,26 +939,16 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - // TODO: there's a lot of boilerplate required for this test even to trigger the expected - // conditions; if the configuration is incorrect, the test may accidentally pass for the - // wrong reasons. Separating responsibilities to other components will help minimize the - // *amount* of boilerplate, but we should also consider setting up test defaults that work - // according to our usual expectations so that we don't overlook false-negative results. - whenever( - resolverListController.getResolversForIntentAsUser( - any(), - any(), - any(), - any(), - any(), - ) - ) - .thenReturn(resolvedTargets) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { getResolversForIntentAsUser(any(), any(), any(), any(), any()) } doReturn + resolvedTargets + } val communicator = mock<ResolverListCommunicator> { - whenever(getReplacementIntent(any(), any())).thenAnswer { invocation -> - invocation.arguments[1] - } + on { getReplacementIntent(any(), any()) } doAnswer { it.arguments[1] as Intent } } val testSubject = ResolverListAdapter( @@ -962,26 +994,16 @@ class ResolverListAdapterTest { ComponentName(PKG_NAME, CLASS_NAME), ComponentName(PKG_NAME_TWO, CLASS_NAME), ) - // TODO: there's a lot of boilerplate required for this test even to trigger the expected - // conditions; if the configuration is incorrect, the test may accidentally pass for the - // wrong reasons. Separating responsibilities to other components will help minimize the - // *amount* of boilerplate, but we should also consider setting up test defaults that work - // according to our usual expectations so that we don't overlook false-negative results. - whenever( - resolverListController.getResolversForIntentAsUser( - any(), - any(), - any(), - any(), - any(), - ) - ) - .thenReturn(resolvedTargets) + val resolverListController = + mock<ResolverListController> { + on { filterIneligibleActivities(any(), any()) } doReturn null + on { filterLowPriority(any(), any()) } doReturn null + on { getResolversForIntentAsUser(any(), any(), any(), any(), any()) } doReturn + resolvedTargets + } val communicator = mock<ResolverListCommunicator> { - whenever(getReplacementIntent(any(), any())).thenAnswer { invocation -> - invocation.arguments[1] - } + on { getReplacementIntent(any(), any()) } doAnswer { it.arguments[1] as Intent } } val testSubject = ResolverListAdapter( @@ -1023,17 +1045,23 @@ class ResolverListAdapterTest { ResolvedComponentInfo( ComponentName(PKG_NAME, CLASS_NAME), targetIntent, - createResolveInfo(component.packageName, component.className) + createResolveInfo(component.packageName, component.className, userHandle) ) result.add(resolvedComponentInfo) } return result } - private fun createResolveInfo(packageName: String, className: String): ResolveInfo = - mock<ResolveInfo> { + private fun createResolveInfo( + packageName: String, + className: String, + handle: UserHandle, + label: String? = null + ): ResolveInfo = + ResolveInfo().apply { activityInfo = createActivityInfo(ComponentName(packageName, className)) - targetUserId = this@ResolverListAdapterTest.userHandle.identifier - userHandle = this@ResolverListAdapterTest.userHandle + targetUserId = handle.identifier + userHandle = handle + nonLocalizedLabel = label } } diff --git a/tests/unit/src/com/android/intentresolver/ShortcutSelectionLogicTest.kt b/tests/unit/src/com/android/intentresolver/ShortcutSelectionLogicTest.kt index 2346d98b..e26dffb8 100644 --- a/tests/unit/src/com/android/intentresolver/ShortcutSelectionLogicTest.kt +++ b/tests/unit/src/com/android/intentresolver/ShortcutSelectionLogicTest.kt @@ -22,13 +22,15 @@ import android.content.Intent import android.content.pm.ShortcutInfo import android.os.UserHandle import android.service.chooser.ChooserTarget -import com.android.intentresolver.chooser.DisplayResolveInfo -import com.android.intentresolver.chooser.TargetInfo import androidx.test.filters.SmallTest import androidx.test.platform.app.InstrumentationRegistry +import com.android.intentresolver.chooser.DisplayResolveInfo +import com.android.intentresolver.chooser.TargetInfo import org.junit.Assert.assertEquals import org.junit.Assert.assertTrue import org.junit.Test +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock private const val PACKAGE_A = "package.a" private const val PACKAGE_B = "package.b" @@ -36,39 +38,43 @@ private const val CLASS_NAME = "./MainActivity" @SmallTest class ShortcutSelectionLogicTest { - private val PERSONAL_USER_HANDLE: UserHandle = InstrumentationRegistry - .getInstrumentation().getTargetContext().getUser() + private val PERSONAL_USER_HANDLE: UserHandle = + InstrumentationRegistry.getInstrumentation().getTargetContext().getUser() - private val packageTargets = HashMap<String, Array<ChooserTarget>>().apply { - arrayOf(PACKAGE_A, PACKAGE_B).forEach { pkg -> - // shortcuts in reverse priority order - val targets = Array(3) { i -> - createChooserTarget( - "Shortcut $i", - (i + 1).toFloat() / 10f, - ComponentName(pkg, CLASS_NAME), - pkg.shortcutId(i), - ) + private val packageTargets = + HashMap<String, Array<ChooserTarget>>().apply { + arrayOf(PACKAGE_A, PACKAGE_B).forEach { pkg -> + // shortcuts in reverse priority order + val targets = + Array(3) { i -> + createChooserTarget( + "Shortcut $i", + (i + 1).toFloat() / 10f, + ComponentName(pkg, CLASS_NAME), + pkg.shortcutId(i), + ) + } + this[pkg] = targets } - this[pkg] = targets } - } - private val baseDisplayInfo = DisplayResolveInfo.newDisplayResolveInfo( + private val baseDisplayInfo = + DisplayResolveInfo.newDisplayResolveInfo( Intent(), ResolverDataProvider.createResolveInfo(3, 0, PERSONAL_USER_HANDLE), "label", "extended info", Intent() - ) + ) - private val otherBaseDisplayInfo = DisplayResolveInfo.newDisplayResolveInfo( + private val otherBaseDisplayInfo = + DisplayResolveInfo.newDisplayResolveInfo( Intent(), ResolverDataProvider.createResolveInfo(4, 0, PERSONAL_USER_HANDLE), "label 2", "extended info 2", Intent() - ) + ) private operator fun Map<String, Array<ChooserTarget>>.get(pkg: String, idx: Int) = this[pkg]?.get(idx) ?: error("missing package $pkg") @@ -78,24 +84,26 @@ class ShortcutSelectionLogicTest { val serviceResults = ArrayList<TargetInfo>() val sc1 = packageTargets[PACKAGE_A, 0] val sc2 = packageTargets[PACKAGE_A, 1] - val testSubject = ShortcutSelectionLogic( - /* maxShortcutTargetsPerApp = */ 1, - /* applySharingAppLimits = */ false - ) + val testSubject = + ShortcutSelectionLogic( + /* maxShortcutTargetsPerApp = */ 1, + /* applySharingAppLimits = */ false + ) - val isUpdated = testSubject.addServiceResults( - /* origTarget = */ baseDisplayInfo, - /* origTargetScore = */ 0.1f, - /* targets = */ listOf(sc1, sc2), - /* isShortcutResult = */ true, - /* directShareToShortcutInfos = */ emptyMap(), - /* directShareToAppTargets = */ emptyMap(), - /* userContext = */ mock(), - /* targetIntent = */ mock(), - /* refererFillInIntent = */ mock(), - /* maxRankedTargets = */ 4, - /* serviceTargets = */ serviceResults - ) + val isUpdated = + testSubject.addServiceResults( + /* origTarget = */ baseDisplayInfo, + /* origTargetScore = */ 0.1f, + /* targets = */ listOf(sc1, sc2), + /* isShortcutResult = */ true, + /* directShareToShortcutInfos = */ emptyMap(), + /* directShareToAppTargets = */ emptyMap(), + /* userContext = */ mock(), + /* targetIntent = */ mock(), + /* refererFillInIntent = */ mock(), + /* maxRankedTargets = */ 4, + /* serviceTargets = */ serviceResults + ) assertTrue("Updates are expected", isUpdated) assertShortcutsInOrder( @@ -110,24 +118,26 @@ class ShortcutSelectionLogicTest { val serviceResults = ArrayList<TargetInfo>() val sc1 = packageTargets[PACKAGE_A, 0] val sc2 = packageTargets[PACKAGE_A, 1] - val testSubject = ShortcutSelectionLogic( - /* maxShortcutTargetsPerApp = */ 1, - /* applySharingAppLimits = */ true - ) + val testSubject = + ShortcutSelectionLogic( + /* maxShortcutTargetsPerApp = */ 1, + /* applySharingAppLimits = */ true + ) - val isUpdated = testSubject.addServiceResults( - /* origTarget = */ baseDisplayInfo, - /* origTargetScore = */ 0.1f, - /* targets = */ listOf(sc1, sc2), - /* isShortcutResult = */ true, - /* directShareToShortcutInfos = */ emptyMap(), - /* directShareToAppTargets = */ emptyMap(), - /* userContext = */ mock(), - /* targetIntent = */ mock(), - /* refererFillInIntent = */ mock(), - /* maxRankedTargets = */ 4, - /* serviceTargets = */ serviceResults - ) + val isUpdated = + testSubject.addServiceResults( + /* origTarget = */ baseDisplayInfo, + /* origTargetScore = */ 0.1f, + /* targets = */ listOf(sc1, sc2), + /* isShortcutResult = */ true, + /* directShareToShortcutInfos = */ emptyMap(), + /* directShareToAppTargets = */ emptyMap(), + /* userContext = */ mock(), + /* targetIntent = */ mock(), + /* refererFillInIntent = */ mock(), + /* maxRankedTargets = */ 4, + /* serviceTargets = */ serviceResults + ) assertTrue("Updates are expected", isUpdated) assertShortcutsInOrder( @@ -142,24 +152,26 @@ class ShortcutSelectionLogicTest { val serviceResults = ArrayList<TargetInfo>() val sc1 = packageTargets[PACKAGE_A, 0] val sc2 = packageTargets[PACKAGE_A, 1] - val testSubject = ShortcutSelectionLogic( - /* maxShortcutTargetsPerApp = */ 1, - /* applySharingAppLimits = */ false - ) + val testSubject = + ShortcutSelectionLogic( + /* maxShortcutTargetsPerApp = */ 1, + /* applySharingAppLimits = */ false + ) - val isUpdated = testSubject.addServiceResults( - /* origTarget = */ baseDisplayInfo, - /* origTargetScore = */ 0.1f, - /* targets = */ listOf(sc1, sc2), - /* isShortcutResult = */ true, - /* directShareToShortcutInfos = */ emptyMap(), - /* directShareToAppTargets = */ emptyMap(), - /* userContext = */ mock(), - /* targetIntent = */ mock(), - /* refererFillInIntent = */ mock(), - /* maxRankedTargets = */ 1, - /* serviceTargets = */ serviceResults - ) + val isUpdated = + testSubject.addServiceResults( + /* origTarget = */ baseDisplayInfo, + /* origTargetScore = */ 0.1f, + /* targets = */ listOf(sc1, sc2), + /* isShortcutResult = */ true, + /* directShareToShortcutInfos = */ emptyMap(), + /* directShareToAppTargets = */ emptyMap(), + /* userContext = */ mock(), + /* targetIntent = */ mock(), + /* refererFillInIntent = */ mock(), + /* maxRankedTargets = */ 1, + /* serviceTargets = */ serviceResults + ) assertTrue("Updates are expected", isUpdated) assertShortcutsInOrder( @@ -176,10 +188,11 @@ class ShortcutSelectionLogicTest { val pkgAsc2 = packageTargets[PACKAGE_A, 1] val pkgBsc1 = packageTargets[PACKAGE_B, 0] val pkgBsc2 = packageTargets[PACKAGE_B, 1] - val testSubject = ShortcutSelectionLogic( - /* maxShortcutTargetsPerApp = */ 1, - /* applySharingAppLimits = */ true - ) + val testSubject = + ShortcutSelectionLogic( + /* maxShortcutTargetsPerApp = */ 1, + /* applySharingAppLimits = */ true + ) testSubject.addServiceResults( /* origTarget = */ baseDisplayInfo, @@ -220,30 +233,31 @@ class ShortcutSelectionLogicTest { val serviceResults = ArrayList<TargetInfo>() val sc1 = packageTargets[PACKAGE_A, 0] val sc2 = packageTargets[PACKAGE_A, 1] - val testSubject = ShortcutSelectionLogic( - /* maxShortcutTargetsPerApp = */ 1, - /* applySharingAppLimits = */ false - ) + val testSubject = + ShortcutSelectionLogic( + /* maxShortcutTargetsPerApp = */ 1, + /* applySharingAppLimits = */ false + ) - val isUpdated = testSubject.addServiceResults( - /* origTarget = */ baseDisplayInfo, - /* origTargetScore = */ 0.1f, - /* targets = */ listOf(sc1, sc2), - /* isShortcutResult = */ true, - /* directShareToShortcutInfos = */ mapOf( - sc1 to createShortcutInfo( - PACKAGE_A.shortcutId(1), - sc1.componentName, 1).apply { - addFlags(ShortcutInfo.FLAG_PINNED) - } - ), - /* directShareToAppTargets = */ emptyMap(), - /* userContext = */ mock(), - /* targetIntent = */ mock(), - /* refererFillInIntent = */ mock(), - /* maxRankedTargets = */ 4, - /* serviceTargets = */ serviceResults - ) + val isUpdated = + testSubject.addServiceResults( + /* origTarget = */ baseDisplayInfo, + /* origTargetScore = */ 0.1f, + /* targets = */ listOf(sc1, sc2), + /* isShortcutResult = */ true, + /* directShareToShortcutInfos = */ mapOf( + sc1 to + createShortcutInfo(PACKAGE_A.shortcutId(1), sc1.componentName, 1).apply { + addFlags(ShortcutInfo.FLAG_PINNED) + } + ), + /* directShareToAppTargets = */ emptyMap(), + /* userContext = */ mock(), + /* targetIntent = */ mock(), + /* refererFillInIntent = */ mock(), + /* maxRankedTargets = */ 4, + /* serviceTargets = */ serviceResults + ) assertTrue("Updates are expected", isUpdated) assertShortcutsInOrder( @@ -259,13 +273,12 @@ class ShortcutSelectionLogicTest { val sc1 = packageTargets[PACKAGE_A, 0] val sc2 = packageTargets[PACKAGE_A, 1] val sc3 = packageTargets[PACKAGE_A, 2] - val testSubject = ShortcutSelectionLogic( - /* maxShortcutTargetsPerApp = */ 1, - /* applySharingAppLimits = */ true - ) - val context = mock<Context> { - whenever(packageManager).thenReturn(mock()) - } + val testSubject = + ShortcutSelectionLogic( + /* maxShortcutTargetsPerApp = */ 1, + /* applySharingAppLimits = */ true + ) + val context = mock<Context> { on { packageManager } doReturn (mock()) } testSubject.addServiceResults( /* origTarget = */ baseDisplayInfo, @@ -291,7 +304,9 @@ class ShortcutSelectionLogicTest { // TODO: consider renaming. Not all `ChooserTarget`s are "shortcuts" and many of our test cases // add results with `isShortcutResult = false` and `directShareToShortcutInfos = emptyMap()`. private fun assertShortcutsInOrder( - expected: List<ChooserTarget>, actual: List<TargetInfo>, msg: String? = "" + expected: List<ChooserTarget>, + actual: List<TargetInfo>, + msg: String? = "" ) { assertEquals(msg, expected.size, actual.size) for (i in expected.indices) { diff --git a/tests/unit/src/com/android/intentresolver/TestHelpers.kt b/tests/unit/src/com/android/intentresolver/TestHelpers.kt index 5b583fef..812ecd1b 100644 --- a/tests/unit/src/com/android/intentresolver/TestHelpers.kt +++ b/tests/unit/src/com/android/intentresolver/TestHelpers.kt @@ -25,25 +25,17 @@ import android.content.pm.ShortcutInfo import android.content.pm.ShortcutManager.ShareShortcutInfo import android.os.Bundle import android.service.chooser.ChooserTarget -import org.mockito.Mockito.`when` as whenever +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock internal fun createShareShortcutInfo( id: String, componentName: ComponentName, rank: Int -): ShareShortcutInfo = - ShareShortcutInfo( - createShortcutInfo(id, componentName, rank), - componentName - ) +): ShareShortcutInfo = ShareShortcutInfo(createShortcutInfo(id, componentName, rank), componentName) -internal fun createShortcutInfo( - id: String, - componentName: ComponentName, - rank: Int -): ShortcutInfo { - val context = mock<Context>() - whenever(context.packageName).thenReturn(componentName.packageName) +internal fun createShortcutInfo(id: String, componentName: ComponentName, rank: Int): ShortcutInfo { + val context = mock<Context> { on { packageName } doReturn componentName.packageName } return ShortcutInfo.Builder(context, id) .setShortLabel("Short Label $id") .setLongLabel("Long Label $id") @@ -60,7 +52,10 @@ internal fun createAppTarget(shortcutInfo: ShortcutInfo) = ) fun createChooserTarget( - title: String, score: Float, componentName: ComponentName, shortcutId: String + title: String, + score: Float, + componentName: ComponentName, + shortcutId: String ): ChooserTarget = ChooserTarget( title, diff --git a/tests/unit/src/com/android/intentresolver/data/repository/UserRepositoryImplTest.kt b/tests/unit/src/com/android/intentresolver/data/repository/UserRepositoryImplTest.kt index a8acbfe1..8db0bb56 100644 --- a/tests/unit/src/com/android/intentresolver/data/repository/UserRepositoryImplTest.kt +++ b/tests/unit/src/com/android/intentresolver/data/repository/UserRepositoryImplTest.kt @@ -22,12 +22,10 @@ import android.os.UserHandle.SYSTEM import android.os.UserHandle.USER_SYSTEM import android.os.UserManager import com.android.intentresolver.coroutines.collectLastValue -import com.android.intentresolver.mock import com.android.intentresolver.platform.FakeUserManager import com.android.intentresolver.platform.FakeUserManager.ProfileType import com.android.intentresolver.shared.model.User import com.android.intentresolver.shared.model.User.Role -import com.android.intentresolver.whenever import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertWithMessage import kotlinx.coroutines.Dispatchers @@ -35,8 +33,9 @@ import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.test.TestScope import kotlinx.coroutines.test.runTest import org.junit.Test -import org.mockito.Mockito -import org.mockito.Mockito.doReturn +import org.mockito.kotlin.any +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock internal class UserRepositoryImplTest { private val userManager = FakeUserManager() @@ -204,24 +203,22 @@ internal class UserRepositoryImplTest { } } -@Suppress("SameParameterValue", "DEPRECATION") +@Suppress("SameParameterValue") private fun mockUserManager(validUser: Int, invalidUser: Int) = mock<UserManager> { val info = UserInfo(validUser, "", "", UserInfo.FLAG_FULL) - doReturn(listOf(info)).whenever(this).getEnabledProfiles(Mockito.anyInt()) - - doReturn(info).whenever(this).getUserInfo(Mockito.eq(validUser)) - - doReturn(listOf<UserInfo>()).whenever(this).getEnabledProfiles(Mockito.eq(invalidUser)) - - doReturn(null).whenever(this).getUserInfo(Mockito.eq(invalidUser)) + on { getEnabledProfiles(any()) } doReturn listOf(info) + on { getUserInfo(validUser) } doReturn info + on { getEnabledProfiles(invalidUser) } doReturn listOf() + on { getUserInfo(invalidUser) } doReturn null } -private fun TestScope.createUserRepository(userManager: FakeUserManager) = - UserRepositoryImpl( +private fun TestScope.createUserRepository(userManager: FakeUserManager): UserRepositoryImpl { + return UserRepositoryImpl( profileParent = userManager.state.primaryUserHandle, userManager = userManager, userEvents = userManager.state.userEvents, scope = backgroundScope, backgroundDispatcher = Dispatchers.Unconfined ) +} diff --git a/tests/unit/src/com/android/intentresolver/emptystate/CrossProfileIntentsCheckerTest.kt b/tests/unit/src/com/android/intentresolver/emptystate/CrossProfileIntentsCheckerTest.kt index 2bcddf59..8cf87ebe 100644 --- a/tests/unit/src/com/android/intentresolver/emptystate/CrossProfileIntentsCheckerTest.kt +++ b/tests/unit/src/com/android/intentresolver/emptystate/CrossProfileIntentsCheckerTest.kt @@ -19,14 +19,14 @@ package com.android.intentresolver.emptystate import android.content.ContentResolver import android.content.Intent import android.content.pm.IPackageManager -import com.android.intentresolver.mock -import com.android.intentresolver.whenever import com.google.common.truth.Truth.assertThat import org.junit.Test import org.mockito.Mockito.any import org.mockito.Mockito.anyInt import org.mockito.Mockito.eq import org.mockito.Mockito.nullable +import org.mockito.kotlin.doReturn +import org.mockito.kotlin.mock class CrossProfileIntentsCheckerTest { private val PERSONAL_USER_ID = 10 @@ -38,15 +38,14 @@ class CrossProfileIntentsCheckerTest { fun testChecker_hasCrossProfileIntents() { val packageManager = mock<IPackageManager> { - whenever( - canForwardTo( - any(Intent::class.java), - nullable(String::class.java), - eq(PERSONAL_USER_ID), - eq(WORK_USER_ID) - ) + on { + canForwardTo( + any(Intent::class.java), + nullable(String::class.java), + eq(PERSONAL_USER_ID), + eq(WORK_USER_ID) ) - .thenReturn(true) + } doReturn (true) } val checker = CrossProfileIntentsChecker(contentResolver, packageManager) val intents = listOf(Intent()) @@ -57,15 +56,14 @@ class CrossProfileIntentsCheckerTest { fun testChecker_noCrossProfileIntents() { val packageManager = mock<IPackageManager> { - whenever( - canForwardTo( - any(Intent::class.java), - nullable(String::class.java), - anyInt(), - anyInt() - ) + on { + canForwardTo( + any(Intent::class.java), + nullable(String::class.java), + anyInt(), + anyInt() ) - .thenReturn(false) + } doReturn (false) } val checker = CrossProfileIntentsChecker(contentResolver, packageManager) val intents = listOf(Intent()) diff --git a/tests/unit/src/com/android/intentresolver/emptystate/EmptyStateUiHelperTest.kt b/tests/unit/src/com/android/intentresolver/emptystate/EmptyStateUiHelperTest.kt index 9efaeb85..174b8d59 100644 --- a/tests/unit/src/com/android/intentresolver/emptystate/EmptyStateUiHelperTest.kt +++ b/tests/unit/src/com/android/intentresolver/emptystate/EmptyStateUiHelperTest.kt @@ -22,15 +22,15 @@ import android.view.ViewGroup import android.widget.FrameLayout import android.widget.TextView import androidx.test.platform.app.InstrumentationRegistry -import com.android.intentresolver.any -import com.android.intentresolver.mock import com.google.common.truth.Truth.assertThat import java.util.Optional import java.util.function.Supplier import org.junit.Before import org.junit.Test -import org.mockito.Mockito.never -import org.mockito.Mockito.verify +import org.mockito.kotlin.any +import org.mockito.kotlin.mock +import org.mockito.kotlin.never +import org.mockito.kotlin.verify class EmptyStateUiHelperTest { private val context = InstrumentationRegistry.getInstrumentation().getContext() |