Fix DataUsageListTest
Using androidx.fragment.app.testing.launchFragment to rewrite the test.
Bug: 315449973
Test: manual - on DataUsageList
Test: unit test
Change-Id: Ief373becb4ac8ab1ba93b8ff3c594b5682c4821e
diff --git a/src/com/android/settings/datausage/DataUsageList.kt b/src/com/android/settings/datausage/DataUsageList.kt
index 6a187d8..3083fb7 100644
--- a/src/com/android/settings/datausage/DataUsageList.kt
+++ b/src/com/android/settings/datausage/DataUsageList.kt
@@ -30,6 +30,7 @@
import androidx.fragment.app.viewModels
import androidx.preference.Preference
import com.android.settings.R
+import com.android.settings.dashboard.DashboardFragment
import com.android.settings.datausage.lib.BillingCycleRepository
import com.android.settings.datausage.lib.NetworkUsageData
import com.android.settings.network.MobileNetworkRepository
@@ -45,43 +46,42 @@
* to inspect based on usage cycle and control through [NetworkPolicy].
*/
@OpenForTesting
-open class DataUsageList : DataUsageBaseFragment() {
- @JvmField
+open class DataUsageList : DashboardFragment() {
@VisibleForTesting
var template: NetworkTemplate? = null
+ private set
- @JvmField
@VisibleForTesting
var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ private set
- private lateinit var usageAmount: Preference
- private var subscriptionInfoEntity: SubscriptionInfoEntity? = null
- private lateinit var dataUsageListAppsController: DataUsageListAppsController
- private lateinit var chartDataUsagePreferenceController: ChartDataUsagePreferenceController
private lateinit var billingCycleRepository: BillingCycleRepository
- private val viewModel: DataUsageListViewModel by viewModels()
+ private var usageAmount: Preference? = null
+ private var subscriptionInfoEntity: SubscriptionInfoEntity? = null
+ private var dataUsageListAppsController: DataUsageListAppsController? = null
+ private var chartDataUsagePreferenceController: ChartDataUsagePreferenceController? = null
+ private var dataUsageListHeaderController: DataUsageListHeaderController? = null
- @VisibleForTesting
- var dataUsageListHeaderController: DataUsageListHeaderController? = null
+ private val viewModel: DataUsageListViewModel by viewModels()
override fun getMetricsCategory() = SettingsEnums.DATA_USAGE_LIST
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
+ billingCycleRepository = BillingCycleRepository(requireContext())
if (requireContext().userManager.isGuestUser) {
Log.e(TAG, "This setting isn't available for guest user")
EventLog.writeEvent(0x534e4554, "262741858", -1 /* UID */, "Guest user")
finish()
return
}
- billingCycleRepository = createBillingCycleRepository()
if (!billingCycleRepository.isBandwidthControlEnabled()) {
Log.w(TAG, "No bandwidth control; leaving")
finish()
return
}
- usageAmount = findPreference(KEY_USAGE_AMOUNT)!!
+ usageAmount = findPreference(KEY_USAGE_AMOUNT)
processArgument()
val template = template
if (template == null) {
@@ -94,12 +94,9 @@
init(template)
}
chartDataUsagePreferenceController = use(ChartDataUsagePreferenceController::class.java)
- chartDataUsagePreferenceController.init(template)
+ .apply { init(template) }
}
- @VisibleForTesting
- open fun createBillingCycleRepository() = BillingCycleRepository(requireContext())
-
override fun onViewCreated(v: View, savedInstanceState: Bundle?) {
super.onViewCreated(v, savedInstanceState)
@@ -117,10 +114,10 @@
::updateSelectedCycle,
)
viewModel.cyclesFlow.collectLatestWithLifecycle(viewLifecycleOwner) { cycles ->
- dataUsageListAppsController.updateCycles(cycles)
+ dataUsageListAppsController?.updateCycles(cycles)
}
viewModel.chartDataFlow.collectLatestWithLifecycle(viewLifecycleOwner) { chartData ->
- chartDataUsagePreferenceController.update(chartData)
+ chartDataUsagePreferenceController?.update(chartData)
}
}
@@ -128,7 +125,7 @@
override fun getLogTag() = TAG
- fun processArgument() {
+ private fun processArgument() {
arguments?.let {
subId = it.getInt(EXTRA_SUB_ID, SubscriptionManager.INVALID_SUBSCRIPTION_ID)
template = it.getParcelable(EXTRA_NETWORK_TEMPLATE, NetworkTemplate::class.java)
@@ -145,8 +142,7 @@
}
}
- @VisibleForTesting
- open fun updateSubscriptionInfoEntity() {
+ private fun updateSubscriptionInfoEntity() {
ThreadUtils.postOnBackgroundThread {
subscriptionInfoEntity =
MobileNetworkRepository.getInstance(context).getSubInfoById(subId.toString())
@@ -154,19 +150,16 @@
}
/** Update chart sweeps and cycle list to reflect [NetworkPolicy] for current [template]. */
- @VisibleForTesting
- fun updatePolicy() {
+ private fun updatePolicy() {
val isBillingCycleModifiable = isBillingCycleModifiable()
dataUsageListHeaderController?.setConfigButtonVisible(isBillingCycleModifiable)
- chartDataUsagePreferenceController.setBillingCycleModifiable(isBillingCycleModifiable)
+ chartDataUsagePreferenceController?.setBillingCycleModifiable(isBillingCycleModifiable)
}
- @VisibleForTesting
- open fun isBillingCycleModifiable(): Boolean {
- return (billingCycleRepository.isModifiable(subId) &&
+ private fun isBillingCycleModifiable(): Boolean =
+ billingCycleRepository.isModifiable(subId) &&
requireContext().getSystemService(SubscriptionManager::class.java)!!
- .getActiveSubscriptionInfo(subId) != null)
- }
+ .getActiveSubscriptionInfo(subId) != null
/**
* Updates the chart and detail data when initial loaded or selected cycle changed.
@@ -174,7 +167,7 @@
private fun updateSelectedCycle(usageData: NetworkUsageData) {
Log.d(TAG, "showing cycle $usageData")
- usageAmount.title = usageData.getDataUsedString(requireContext())
+ usageAmount?.title = usageData.getDataUsedString(requireContext())
viewModel.selectedCycleFlow.value = usageData
updateApps(usageData)
@@ -182,7 +175,7 @@
/** Updates applications data usage. */
private fun updateApps(usageData: NetworkUsageData) {
- dataUsageListAppsController.update(
+ dataUsageListAppsController?.update(
carrierId = subscriptionInfoEntity?.carrierId,
startTime = usageData.startTime,
endTime = usageData.endTime,
diff --git a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt b/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt
deleted file mode 100644
index 39b8446..0000000
--- a/tests/robotests/src/com/android/settings/datausage/DataUsageListTest.kt
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2023 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.settings.datausage
-
-import android.content.Context
-import android.content.Intent
-import android.net.NetworkTemplate
-import android.os.Bundle
-import android.os.UserManager
-import android.provider.Settings
-import androidx.preference.Preference
-import androidx.test.core.app.ApplicationProvider
-import com.android.settings.datausage.DataUsageListTest.ShadowDataUsageBaseFragment
-import com.android.settings.datausage.TemplatePreference.NetworkServices
-import com.android.settings.datausage.lib.BillingCycleRepository
-import com.android.settings.testutils.FakeFeatureFactory
-import com.android.settingslib.NetworkPolicyEditor
-import com.android.settingslib.core.AbstractPreferenceController
-import com.google.common.truth.Truth.assertThat
-import org.junit.Before
-import org.junit.Rule
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.Mock
-import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.doReturn
-import org.mockito.Mockito.mock
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.Mockito.`when`
-import org.mockito.Spy
-import org.mockito.junit.MockitoJUnit
-import org.mockito.junit.MockitoRule
-import org.robolectric.RobolectricTestRunner
-import org.robolectric.annotation.Config
-import org.robolectric.annotation.Implementation
-import org.robolectric.annotation.Implements
-import org.robolectric.util.ReflectionHelpers
-
-@RunWith(RobolectricTestRunner::class)
-@Config(shadows = [ShadowDataUsageBaseFragment::class])
-class DataUsageListTest {
- @get:Rule
- val mockito: MockitoRule = MockitoJUnit.rule()
-
- @Mock
- private lateinit var networkServices: NetworkServices
-
- @Mock
- private lateinit var userManager: UserManager
-
- @Mock
- private lateinit var billingCycleRepository: BillingCycleRepository
-
- @Mock
- private lateinit var dataUsageListHeaderController: DataUsageListHeaderController
-
- @Spy
- private val context: Context = ApplicationProvider.getApplicationContext()
-
- @Spy
- private val dataUsageList = TestDataUsageList()
-
- @Before
- fun setUp() {
- FakeFeatureFactory.setupForTest()
- networkServices.mPolicyEditor = mock(NetworkPolicyEditor::class.java)
- doReturn(context).`when`(dataUsageList).context
- doReturn(userManager).`when`(context).getSystemService(UserManager::class.java)
- doReturn(false).`when`(userManager).isGuestUser
- ReflectionHelpers.setField(dataUsageList, "services", networkServices)
- doNothing().`when`(dataUsageList).updateSubscriptionInfoEntity()
- `when`(billingCycleRepository.isBandwidthControlEnabled()).thenReturn(true)
- dataUsageList.dataUsageListHeaderController = dataUsageListHeaderController
- }
-
- @Test
- fun onCreate_isNotGuestUser_shouldNotFinish() {
- dataUsageList.template = mock<NetworkTemplate>(NetworkTemplate::class.java)
- doReturn(false).`when`(userManager).isGuestUser
- doNothing().`when`(dataUsageList).processArgument()
- dataUsageList.onCreate(null)
- verify(dataUsageList, never()).finish()
- }
-
- @Test
- fun onCreate_isGuestUser_shouldFinish() {
- doReturn(true).`when`(userManager).isGuestUser
- dataUsageList.onCreate(null)
- verify(dataUsageList).finish()
- }
-
- @Test
- fun processArgument_shouldGetTemplateFromArgument() {
- val args = Bundle()
- args.putParcelable(
- DataUsageList.EXTRA_NETWORK_TEMPLATE, mock(
- NetworkTemplate::class.java
- )
- )
- args.putInt(DataUsageList.EXTRA_SUB_ID, 3)
- dataUsageList.arguments = args
- dataUsageList.processArgument()
- assertThat(dataUsageList.template).isNotNull()
- assertThat(dataUsageList.subId).isEqualTo(3)
- }
-
- @Test
- fun processArgument_fromIntent_shouldGetTemplateFromIntent() {
- val intent = Intent()
- intent.putExtra(
- Settings.EXTRA_NETWORK_TEMPLATE, mock(
- NetworkTemplate::class.java
- )
- )
- intent.putExtra(Settings.EXTRA_SUB_ID, 3)
- doReturn(intent).`when`(dataUsageList).intent
- dataUsageList.processArgument()
- assertThat(dataUsageList.template).isNotNull()
- assertThat(dataUsageList.subId).isEqualTo(3)
- }
-
- @Test
- fun updatePolicy_setConfigButtonVisible() {
- dataUsageList.template = mock(NetworkTemplate::class.java)
- dataUsageList.onCreate(null)
-
- dataUsageList.updatePolicy()
-
- verify(dataUsageListHeaderController).setConfigButtonVisible(true)
- }
-
- @Implements(DataUsageBaseFragment::class)
- class ShadowDataUsageBaseFragment {
- @Implementation
- fun onCreate(@Suppress("UNUSED_PARAMETER") icicle: Bundle?) {
- // do nothing
- }
- }
-
- open inner class TestDataUsageList : DataUsageList() {
- override fun <T : AbstractPreferenceController?> use(clazz: Class<T>): T = mock(clazz)
-
- @Suppress("UNCHECKED_CAST")
- override fun <T : Preference?> findPreference(key: CharSequence): T =
- mock(Preference::class.java) as T
-
- public override fun getIntent() = Intent()
-
- override fun createBillingCycleRepository() = billingCycleRepository
-
- override fun isBillingCycleModifiable() = true
- }
-}
diff --git a/tests/spa_unit/Android.bp b/tests/spa_unit/Android.bp
index c3e99f7..4df6254 100644
--- a/tests/spa_unit/Android.bp
+++ b/tests/spa_unit/Android.bp
@@ -34,6 +34,7 @@
"androidx.compose.runtime_runtime",
"androidx.test.ext.junit",
"androidx.test.runner",
+ "androidx.fragment_fragment-testing",
"flag-junit",
"mockito-target-extended-minus-junit4",
],
diff --git a/tests/spa_unit/src/com/android/settings/datausage/DataUsageListTest.kt b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListTest.kt
new file mode 100644
index 0000000..29ec0ee
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/datausage/DataUsageListTest.kt
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2023 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.settings.datausage
+
+import android.content.Context
+import android.content.Intent
+import android.net.NetworkTemplate
+import android.os.UserManager
+import android.provider.Settings
+import android.telephony.SubscriptionManager
+import androidx.core.os.bundleOf
+import androidx.fragment.app.testing.launchFragment
+import androidx.fragment.app.testing.withFragment
+import androidx.lifecycle.Lifecycle
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settingslib.spaprivileged.framework.common.userManager
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.stub
+
+private val mockUserManager: UserManager = mock<UserManager>()
+
+private val mockContext: Context = spy(ApplicationProvider.getApplicationContext()) {
+ on { userManager } doReturn mockUserManager
+}
+
+private var fakeIntent = Intent()
+
+@RunWith(AndroidJUnit4::class)
+class DataUsageListTest {
+
+ @Before
+ fun setUp() {
+ mockUserManager.stub {
+ on { isGuestUser } doReturn false
+ }
+ fakeIntent = Intent()
+ }
+
+ @Test
+ fun launchFragment_withoutArguments_finish() {
+ val scenario = launchFragment<TestDataUsageList>(initialState = Lifecycle.State.CREATED)
+
+ scenario.withFragment {
+ assertThat(template).isNull()
+ assertThat(subId).isEqualTo(SubscriptionManager.INVALID_SUBSCRIPTION_ID)
+ assertThat(activity!!.isFinishing).isTrue()
+ }
+ }
+
+ @Test
+ fun launchFragment_isGuestUser_finish() {
+ mockUserManager.stub {
+ on { isGuestUser } doReturn true
+ }
+ val fragmentArgs = bundleOf(
+ DataUsageList.EXTRA_NETWORK_TEMPLATE to mock<NetworkTemplate>(),
+ DataUsageList.EXTRA_SUB_ID to 3,
+ )
+
+ val scenario = launchFragment<TestDataUsageList>(
+ fragmentArgs = fragmentArgs,
+ initialState = Lifecycle.State.CREATED,
+ )
+
+ scenario.withFragment {
+ assertThat(activity!!.isFinishing).isTrue()
+ }
+ }
+
+ @Test
+ fun launchFragment_withArguments_getTemplateFromArgument() {
+ val fragmentArgs = bundleOf(
+ DataUsageList.EXTRA_NETWORK_TEMPLATE to mock<NetworkTemplate>(),
+ DataUsageList.EXTRA_SUB_ID to 3,
+ )
+
+ val scenario = launchFragment<TestDataUsageList>(
+ fragmentArgs = fragmentArgs,
+ initialState = Lifecycle.State.CREATED,
+ )
+
+ scenario.withFragment {
+ assertThat(template).isNotNull()
+ assertThat(subId).isEqualTo(3)
+ assertThat(activity!!.isFinishing).isFalse()
+ }
+ }
+
+ @Test
+ fun launchFragment_withIntent_getTemplateFromIntent() {
+ fakeIntent = Intent().apply {
+ putExtra(Settings.EXTRA_NETWORK_TEMPLATE, mock<NetworkTemplate>())
+ putExtra(Settings.EXTRA_SUB_ID, 2)
+ }
+
+ val scenario = launchFragment<TestDataUsageList>(initialState = Lifecycle.State.CREATED)
+
+ scenario.withFragment {
+ assertThat(template).isNotNull()
+ assertThat(subId).isEqualTo(2)
+ assertThat(activity!!.isFinishing).isFalse()
+ }
+ }
+}
+
+class TestDataUsageList : DataUsageList() {
+ override fun getContext() = mockContext
+
+ override fun getIntent() = fakeIntent
+}