From f4d751871063af18154996be6b79d651cd97ae52 Mon Sep 17 00:00:00 2001 From: Chun-Ku Lin Date: Tue, 23 May 2023 17:32:44 +0000 Subject: [PATCH] Clean up test with Robolectric's way to launch a fragment with an activity. Robolectric has shadows for many Android framework's code. With the help of Robolectric, We don't need to use mock the return value of every method Activity or Fragment has. Bug: 283885638 Test: atest AccessibilityDetailsSettingsFragmentTest Change-Id: I77dfa755e3a1b6a240a06f74b5a6c5984534c831 --- ...essibilityDetailsSettingsFragmentTest.java | 142 +++++++++--------- .../shadow/ShadowDevicePolicyManager.java | 13 ++ 2 files changed, 85 insertions(+), 70 deletions(-) diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java index bf29c95984a..2f6ab9f07b6 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityDetailsSettingsFragmentTest.java @@ -22,13 +22,9 @@ import static com.android.internal.accessibility.AccessibilityShortcutController import static com.google.common.truth.Truth.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.anyInt; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; - import android.accessibilityservice.AccessibilityServiceInfo; +import android.app.Activity; +import android.app.admin.DevicePolicyManager; import android.app.settings.SettingsEnums; import android.content.ComponentName; import android.content.Context; @@ -36,27 +32,25 @@ import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; -import android.os.Bundle; import android.util.FeatureFlagUtils; import android.view.accessibility.AccessibilityManager; -import androidx.fragment.app.FragmentActivity; +import androidx.test.core.app.ApplicationProvider; import com.android.settings.SettingsActivity; -import com.android.settings.testutils.shadow.ShadowFragment; +import com.android.settings.testutils.shadow.ShadowDevicePolicyManager; + +import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; -import org.robolectric.RuntimeEnvironment; +import org.robolectric.Shadows; import org.robolectric.annotation.Config; import org.robolectric.shadow.api.Shadow; import org.robolectric.shadows.ShadowAccessibilityManager; +import org.robolectric.shadows.androidx.fragment.FragmentController; import org.xmlpull.v1.XmlPullParserException; import java.io.IOException; @@ -64,112 +58,116 @@ import java.util.ArrayList; import java.util.List; /** Tests for {@link AccessibilityDetailsSettingsFragment}. */ -@Config(shadows = ShadowFragment.class) +@Config(shadows = ShadowDevicePolicyManager.class) @RunWith(RobolectricTestRunner.class) public class AccessibilityDetailsSettingsFragmentTest { - private final static String PACKAGE_NAME = "com.foo.bar"; - private final static String CLASS_NAME = PACKAGE_NAME + ".fake_a11y_service"; - private final static String COMPONENT_NAME = PACKAGE_NAME + "/" + CLASS_NAME; + private static final String PACKAGE_NAME = "com.foo.bar"; + private static final String CLASS_NAME = PACKAGE_NAME + ".fake_a11y_service"; + private static final String COMPONENT_NAME = PACKAGE_NAME + "/" + CLASS_NAME; private Context mContext; - private AccessibilityDetailsSettingsFragment mFragment; - private ShadowAccessibilityManager mShadowAccessibilityManager; - @Captor - private ArgumentCaptor mIntentArgumentCaptor; - @Mock private FragmentActivity mActivity; + + private FragmentController mFragmentController; @Before public void setUp() { - MockitoAnnotations.initMocks(this); - mContext = spy(RuntimeEnvironment.application); - mFragment = spy(new AccessibilityDetailsSettingsFragment()); - mShadowAccessibilityManager = Shadow.extract(AccessibilityManager.getInstance(mContext)); - mShadowAccessibilityManager.setInstalledAccessibilityServiceList(getMockServiceList()); - - doReturn(mActivity).when(mFragment).getActivity(); - doReturn(mContext).when(mFragment).getContext(); + mContext = ApplicationProvider.getApplicationContext(); + ShadowAccessibilityManager shadowAccessibilityManager = Shadow.extract( + AccessibilityManager.getInstance(mContext)); + shadowAccessibilityManager.setInstalledAccessibilityServiceList(getMockServiceList()); } @Test public void onCreate_afterSuccessfullyLaunch_shouldBeFinished() { final Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME); - doReturn(intent).when(mActivity).getIntent(); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + intent); - mFragment.onCreate(Bundle.EMPTY); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); - verify(mActivity).finish(); + assertThat(fragment.getActivity().isFinishing()).isTrue(); } @Test public void onCreate_hasValidExtraComponentName_launchExpectedFragment() { - final Intent intent = new Intent(); + Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME); - doReturn(intent).when(mActivity).getIntent(); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + intent); - mFragment.onCreate(Bundle.EMPTY); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); - assertStartActivityWithExpectedFragment(mActivity, + assertStartActivityWithExpectedFragment(fragment.getActivity(), ToggleAccessibilityServicePreferenceFragment.class.getName()); } @Test public void onCreate_hasInvalidExtraComponentName_launchAccessibilitySettings() { - final Intent intent = new Intent(); + Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, PACKAGE_NAME + "/.service"); - doReturn(intent).when(mActivity).getIntent(); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + intent); - mFragment.onCreate(Bundle.EMPTY); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); - assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName()); + assertStartActivityWithExpectedFragment(fragment.getActivity(), + AccessibilitySettings.class.getName()); } @Test public void onCreate_hasNoExtraComponentName_launchAccessibilitySettings() { - final Intent intent = new Intent(); - doReturn(intent).when(mActivity).getIntent(); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + new Intent()); - mFragment.onCreate(Bundle.EMPTY); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); - assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName()); + assertStartActivityWithExpectedFragment(fragment.getActivity(), + AccessibilitySettings.class.getName()); } @Test public void onCreate_extraComponentNameIsDisallowed_launchAccessibilitySettings() { - final Intent intent = new Intent(); + Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, COMPONENT_NAME); - doReturn(intent).when(mActivity).getIntent(); - doReturn(false).when(mFragment).isServiceAllowed(anyInt(), any()); + DevicePolicyManager dpm = mContext.getSystemService( + DevicePolicyManager.class); + ((ShadowDevicePolicyManager) Shadows.shadowOf(dpm)).setPermittedAccessibilityServices( + ImmutableList.of()); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + intent); - mFragment.onCreate(Bundle.EMPTY); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); - assertStartActivityWithExpectedFragment(mActivity, AccessibilitySettings.class.getName()); + assertStartActivityWithExpectedFragment(fragment.getActivity(), + AccessibilitySettings.class.getName()); } @Test public void onCreate_magnificationComponentName_launchMagnificationFragment() { - final Intent intent = new Intent(); + Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, MAGNIFICATION_COMPONENT_NAME.flattenToString()); - doReturn(intent).when(mActivity).getIntent(); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + intent); - mFragment.onCreate(Bundle.EMPTY); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); - - assertStartActivityWithExpectedFragment(mActivity, + assertStartActivityWithExpectedFragment(fragment.getActivity(), ToggleScreenMagnificationPreferenceFragment.class.getName()); } @Test public void onCreate_accessibilityButton_launchAccessibilityButtonFragment() { - final Intent intent = new Intent(); + Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ACCESSIBILITY_BUTTON_COMPONENT_NAME.flattenToString()); - doReturn(intent).when(mActivity).getIntent(); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + intent); - mFragment.onCreate(Bundle.EMPTY); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); - assertStartActivityWithExpectedFragment(mActivity, + assertStartActivityWithExpectedFragment(fragment.getActivity(), AccessibilityButtonFragment.class.getName()); } @@ -177,20 +175,25 @@ public class AccessibilityDetailsSettingsFragmentTest { public void onCreate_hearingAidsComponentName_launchAccessibilityHearingAidsFragment() { FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_ACCESSIBILITY_HEARING_AID_PAGE, true); - final Intent intent = new Intent(); + Intent intent = new Intent(); intent.putExtra(Intent.EXTRA_COMPONENT_NAME, ACCESSIBILITY_HEARING_AIDS_COMPONENT_NAME.flattenToString()); - doReturn(intent).when(mActivity).getIntent(); - mFragment.onCreate(Bundle.EMPTY); + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment(), + intent); - assertStartActivityWithExpectedFragment(mActivity, + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); + + assertStartActivityWithExpectedFragment(fragment.getActivity(), AccessibilityHearingAidsFragment.class.getName()); } @Test public void getMetricsCategory_returnsCorrectCategory() { - assertThat(mFragment.getMetricsCategory()).isEqualTo( + mFragmentController = FragmentController.of(new AccessibilityDetailsSettingsFragment()); + AccessibilityDetailsSettingsFragment fragment = mFragmentController.create().get(); + + assertThat(fragment.getMetricsCategory()).isEqualTo( SettingsEnums.ACCESSIBILITY_DETAILS_SETTINGS); } @@ -224,10 +227,9 @@ public class AccessibilityDetailsSettingsFragmentTest { return infoList; } - private void assertStartActivityWithExpectedFragment(Context mockContext, String fragmentName) { - verify(mockContext).startActivity(mIntentArgumentCaptor.capture()); - assertThat(mIntentArgumentCaptor.getValue() - .getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)) - .isEqualTo(fragmentName); + private void assertStartActivityWithExpectedFragment(Activity activity, String fragmentName) { + Intent intent = Shadows.shadowOf(activity).getNextStartedActivity(); + assertThat(intent.getStringExtra(SettingsActivity.EXTRA_SHOW_FRAGMENT)).isEqualTo( + fragmentName); } } diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java index 039650323e6..76c675ac69a 100644 --- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java +++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowDevicePolicyManager.java @@ -19,6 +19,7 @@ import org.robolectric.annotation.Implements; import org.robolectric.shadow.api.Shadow; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Objects; @@ -36,6 +37,8 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev private int mPasswordMinLength = 0; private int mPasswordMinSymbols = 0; + private List mPermittedAccessibilityServices = null; + public void setShortSupportMessageForUser(ComponentName admin, int userHandle, String message) { mSupportMessagesMap.put(Objects.hash(admin, userHandle), message); } @@ -122,6 +125,16 @@ public class ShadowDevicePolicyManager extends org.robolectric.shadows.ShadowDev mPasswordMinSymbols = numOfSymbols; } + public void setPermittedAccessibilityServices(List permittedAccessibilityServices) { + mPermittedAccessibilityServices = permittedAccessibilityServices; + } + + @Implementation + @Nullable + public List getPermittedAccessibilityServices(int userId) { + return mPermittedAccessibilityServices; + } + public static ShadowDevicePolicyManager getShadow() { return (ShadowDevicePolicyManager) Shadow.extract( RuntimeEnvironment.application.getSystemService(DevicePolicyManager.class));