commit 600e0fb902f88987e06c260b01ca426cb77ef382
parent c26815f243d858c4097554f2879a8ff004f1dae8
Author: mcarare <48995920+mcarare@users.noreply.github.com>
Date: Fri, 14 Nov 2025 11:46:10 +0000
Bug 1996628 - Remove mockkStatic from DefaultPocketStoriesControllerTest. r=android-reviewers,giorga
This patch removes the usage of `mockkStatic` in `DefaultPocketStoriesControllerTest` to simplify the test setup. The mocked static `getCurrentFlightImpressions()` extension function is replaced by providing realistic test data for the `caps` property of the story objects directly within the tests.
Differential Revision: https://phabricator.services.mozilla.com/D272618
Diffstat:
1 file changed, 151 insertions(+), 129 deletions(-)
diff --git a/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/pocket/DefaultPocketStoriesControllerTest.kt b/mobile/android/fenix/app/src/test/java/org/mozilla/fenix/home/pocket/DefaultPocketStoriesControllerTest.kt
@@ -9,7 +9,6 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import io.mockk.coVerify
import io.mockk.every
import io.mockk.mockk
-import io.mockk.mockkStatic
import io.mockk.spyk
import io.mockk.verify
import io.mockk.verifyOrder
@@ -17,9 +16,10 @@ import mozilla.components.service.pocket.PocketStory
import mozilla.components.service.pocket.PocketStory.ContentRecommendation
import mozilla.components.service.pocket.PocketStory.PocketRecommendedStory
import mozilla.components.service.pocket.PocketStory.PocketSponsoredStory
+import mozilla.components.service.pocket.PocketStory.PocketSponsoredStoryCaps
import mozilla.components.service.pocket.PocketStory.SponsoredContent
import mozilla.components.service.pocket.PocketStory.SponsoredContentCallbacks
-import mozilla.components.service.pocket.ext.getCurrentFlightImpressions
+import mozilla.components.service.pocket.PocketStory.SponsoredContentFrequencyCaps
import mozilla.components.support.test.robolectric.testContext
import mozilla.components.support.test.rule.MainCoroutineRule
import org.junit.Assert.assertEquals
@@ -62,6 +62,46 @@ class DefaultPocketStoriesControllerTest {
private val scope = coroutinesTestRule.scope
+ private val nowInSeconds = System.currentTimeMillis() / 1000
+ private val flightPeriod = 100
+
+ // Data for "shown" tests, expecting 3 previous impressions.
+ private val impressionsForShownTest = listOf(
+ nowInSeconds - flightPeriod * 2, // This one is old and will be filtered out
+ nowInSeconds - flightPeriod / 2,
+ nowInSeconds - flightPeriod / 3,
+ nowInSeconds - flightPeriod / 4,
+ )
+ private val storyCapsForShownTest = PocketSponsoredStoryCaps(
+ currentImpressions = impressionsForShownTest,
+ lifetimeCount = 10,
+ flightCount = 5,
+ flightPeriod = flightPeriod,
+ )
+ private val contentCapsForShownTest = SponsoredContentFrequencyCaps(
+ currentImpressions = impressionsForShownTest,
+ flightCount = 5,
+ flightPeriod = flightPeriod,
+ )
+
+ // Data for "clicked" tests, expecting 2 previous impressions.
+ private val impressionsForClickedTest = listOf(
+ nowInSeconds - flightPeriod * 2, // This one is old and will be filtered out
+ nowInSeconds - flightPeriod / 2,
+ nowInSeconds - flightPeriod / 3,
+ )
+ private val storyCapsForClickedTest = PocketSponsoredStoryCaps(
+ currentImpressions = impressionsForClickedTest,
+ lifetimeCount = 10,
+ flightCount = 5,
+ flightPeriod = flightPeriod,
+ )
+ private val contentCapsForClickedTest = SponsoredContentFrequencyCaps(
+ currentImpressions = impressionsForClickedTest,
+ flightCount = 5,
+ flightPeriod = flightPeriod,
+ )
+
@Test
fun `GIVEN a category is selected WHEN that same category is clicked THEN deselect it and record telemetry`() {
val category1 = PocketRecommendedStoriesCategory("cat1", emptyList())
@@ -216,38 +256,34 @@ class DefaultPocketStoriesControllerTest {
every { shim.click } returns "testClickShim"
every { shim.impression } returns "testImpressionShim"
every { id } returns 123
+ every { caps } returns storyCapsForShownTest
}
var wasPingSent = false
- mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") {
- // Simulate that the story was already shown 3 times.
- every { storyShown.getCurrentFlightImpressions() } returns listOf(2L, 3L, 7L)
- // Test that the spoc ping is immediately sent with the needed data.
- val job = Pings.spoc.testBeforeNextSubmit { reason ->
- assertEquals(storyShown.shim.impression, Pocket.spocShim.testGetValue())
- assertEquals(Pings.spocReasonCodes.impression.name, reason?.name)
- wasPingSent = true
- }
-
- controller.handleStoryShown(storyShown, storyPosition = Triple(1, 2, 3))
- job.join()
-
- verify {
- store.dispatch(
- ContentRecommendationsAction.PocketStoriesShown(
- impressions = listOf(
- PocketImpression(story = storyShown, position = 3),
- ),
+ val job = Pings.spoc.testBeforeNextSubmit { reason ->
+ assertEquals(storyShown.shim.impression, Pocket.spocShim.testGetValue())
+ assertEquals(Pings.spocReasonCodes.impression.name, reason?.name)
+ wasPingSent = true
+ }
+
+ controller.handleStoryShown(storyShown, storyPosition = Triple(1, 2, 3))
+ job.join()
+
+ verify {
+ store.dispatch(
+ ContentRecommendationsAction.PocketStoriesShown(
+ impressions = listOf(
+ PocketImpression(story = storyShown, position = 3),
),
- )
- }
- assertNotNull(Pocket.homeRecsSpocShown.testGetValue())
- assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size)
- val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra
- assertEquals("123", data?.entries?.first { it.key == "spoc_id" }?.value)
- assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value)
- assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value)
- assertTrue(wasPingSent)
+ ),
+ )
}
+ assertNotNull(Pocket.homeRecsSpocShown.testGetValue())
+ assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size)
+ val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra
+ assertEquals("123", data?.entries?.first { it.key == "spoc_id" }?.value)
+ assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value)
+ assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value)
+ assertTrue(wasPingSent)
}
@Test
@@ -266,31 +302,27 @@ class DefaultPocketStoriesControllerTest {
excerpt = "Mozilla Firefox",
sponsor = "Mozilla",
blockKey = "1",
- caps = mockk(relaxed = true),
+ caps = contentCapsForShownTest,
priority = 3,
)
- mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") {
- every { sponsoredContent.getCurrentFlightImpressions() } returns listOf(2L, 3L, 7L)
-
- controller.handleStoryShown(sponsoredContent, storyPosition = Triple(1, 2, 3))
+ controller.handleStoryShown(sponsoredContent, storyPosition = Triple(1, 2, 3))
- assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size)
+ assertEquals(1, Pocket.homeRecsSpocShown.testGetValue()!!.size)
- val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra
- assertEquals(2, data?.size)
- assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value)
- assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value)
+ val data = Pocket.homeRecsSpocShown.testGetValue()!!.single().extra
+ assertEquals(2, data?.size)
+ assertEquals("1x2", data?.entries?.first { it.key == "position" }?.value)
+ assertEquals("4", data?.entries?.first { it.key == "times_shown" }?.value)
- verify {
- store.dispatch(
- ContentRecommendationsAction.PocketStoriesShown(
- impressions = listOf(
- PocketImpression(story = sponsoredContent, position = 3),
- ),
+ verify {
+ store.dispatch(
+ ContentRecommendationsAction.PocketStoriesShown(
+ impressions = listOf(
+ PocketImpression(story = sponsoredContent, position = 3),
),
- )
- }
+ ),
+ )
}
}
@@ -406,41 +438,38 @@ class DefaultPocketStoriesControllerTest {
every { impression } returns "testImpressionShim"
},
priority = 3,
- caps = mockk(relaxed = true),
+ caps = storyCapsForClickedTest,
)
val controller = createController()
var wasPingSent = false
assertNull(Pocket.homeRecsSpocClicked.testGetValue())
- mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") {
- // Simulate that the story was already shown 2 times.
- every { storyClicked.getCurrentFlightImpressions() } returns listOf(2L, 3L)
- // Test that the spoc ping is immediately sent with the needed data.
- val job = Pings.spoc.testBeforeNextSubmit { reason ->
- assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue())
- assertEquals(Pings.spocReasonCodes.click.name, reason?.name)
- wasPingSent = true
- }
-
- controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4))
- job.join()
-
- verify {
- navController.navigate(R.id.browserFragment)
- fenixBrowserUseCases.loadUrlOrSearch(
- searchTermOrURL = storyClicked.url,
- newTab = true,
- private = false,
- )
- }
-
- assertNotNull(Pocket.homeRecsSpocClicked.testGetValue())
- assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size)
- val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra
- assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value)
- assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value)
- assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value)
- assertTrue(wasPingSent)
+
+ // Test that the spoc ping is immediately sent with the needed data.
+ val job = Pings.spoc.testBeforeNextSubmit { reason ->
+ assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue())
+ assertEquals(Pings.spocReasonCodes.click.name, reason?.name)
+ wasPingSent = true
}
+
+ controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4))
+ job.join()
+
+ verify {
+ navController.navigate(R.id.browserFragment)
+ fenixBrowserUseCases.loadUrlOrSearch(
+ searchTermOrURL = storyClicked.url,
+ newTab = true,
+ private = false,
+ )
+ }
+
+ assertNotNull(Pocket.homeRecsSpocClicked.testGetValue())
+ assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size)
+ val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra
+ assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value)
+ assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value)
+ assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value)
+ assertTrue(wasPingSent)
}
@Test
@@ -458,41 +487,38 @@ class DefaultPocketStoriesControllerTest {
every { impression } returns "testImpressionShim"
},
priority = 3,
- caps = mockk(relaxed = true),
+ caps = storyCapsForClickedTest,
)
val controller = createController()
var wasPingSent = false
assertNull(Pocket.homeRecsSpocClicked.testGetValue())
- mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") {
- // Simulate that the story was already shown 2 times.
- every { storyClicked.getCurrentFlightImpressions() } returns listOf(2L, 3L)
- // Test that the spoc ping is immediately sent with the needed data.
- val job = Pings.spoc.testBeforeNextSubmit { reason ->
- assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue())
- assertEquals(Pings.spocReasonCodes.click.name, reason?.name)
- wasPingSent = true
- }
-
- controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4))
- job.join()
-
- verify {
- navController.navigate(R.id.browserFragment)
- fenixBrowserUseCases.loadUrlOrSearch(
- searchTermOrURL = storyClicked.url,
- newTab = false,
- private = false,
- )
- }
-
- assertNotNull(Pocket.homeRecsSpocClicked.testGetValue())
- assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size)
- val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra
- assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value)
- assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value)
- assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value)
- assertTrue(wasPingSent)
+
+ // Test that the spoc ping is immediately sent with the needed data.
+ val job = Pings.spoc.testBeforeNextSubmit { reason ->
+ assertEquals(storyClicked.shim.click, Pocket.spocShim.testGetValue())
+ assertEquals(Pings.spocReasonCodes.click.name, reason?.name)
+ wasPingSent = true
+ }
+
+ controller.handleStoryClicked(storyClicked, storyPosition = Triple(2, 3, 4))
+ job.join()
+
+ verify {
+ navController.navigate(R.id.browserFragment)
+ fenixBrowserUseCases.loadUrlOrSearch(
+ searchTermOrURL = storyClicked.url,
+ newTab = false,
+ private = false,
+ )
}
+
+ assertNotNull(Pocket.homeRecsSpocClicked.testGetValue())
+ assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size)
+ val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra
+ assertEquals("7", data?.entries?.first { it.key == "spoc_id" }?.value)
+ assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value)
+ assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value)
+ assertTrue(wasPingSent)
}
@Test
@@ -509,33 +535,29 @@ class DefaultPocketStoriesControllerTest {
excerpt = "Mozilla Firefox",
sponsor = "Mozilla",
blockKey = "1",
- caps = mockk(relaxed = true),
+ caps = contentCapsForClickedTest,
priority = 3,
)
val controller = createController()
assertNull(Pocket.homeRecsSpocClicked.testGetValue())
- mockkStatic("mozilla.components.service.pocket.ext.PocketStoryKt") {
- every { sponsoredContent.getCurrentFlightImpressions() } returns listOf(2L, 3L)
-
- controller.handleStoryClicked(sponsoredContent, storyPosition = Triple(2, 3, 4))
-
- assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size)
- val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra
- assertEquals(2, data?.size)
- assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value)
- assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value)
-
- coVerify {
- navController.navigate(R.id.browserFragment)
- fenixBrowserUseCases.loadUrlOrSearch(
- searchTermOrURL = sponsoredContent.url,
- newTab = true,
- private = false,
- )
- marsUseCases.recordInteraction(sponsoredContent.callbacks.clickUrl)
- }
+ controller.handleStoryClicked(sponsoredContent, storyPosition = Triple(2, 3, 4))
+
+ assertEquals(1, Pocket.homeRecsSpocClicked.testGetValue()!!.size)
+ val data = Pocket.homeRecsSpocClicked.testGetValue()!!.single().extra
+ assertEquals(2, data?.size)
+ assertEquals("2x3", data?.entries?.first { it.key == "position" }?.value)
+ assertEquals("3", data?.entries?.first { it.key == "times_shown" }?.value)
+
+ coVerify {
+ navController.navigate(R.id.browserFragment)
+ fenixBrowserUseCases.loadUrlOrSearch(
+ searchTermOrURL = sponsoredContent.url,
+ newTab = true,
+ private = false,
+ )
+ marsUseCases.recordInteraction(sponsoredContent.callbacks.clickUrl)
}
}