From 46e1dd6c9c6316a42abf712c4522491725feadb1 Mon Sep 17 00:00:00 2001 From: Bryan Van Deusen Date: Wed, 21 Oct 2026 08:03:51 -0400 Subject: [PATCH] test(android): run the sync pass in the test body, not through init's background collector (#5654) advanceUntilIdle does not count backgroundScope work as pending, so the pass init would start never ran. The network state is Offline so construction starts none, and each test calls syncSafe itself and asserts lastSyncError stays null. Co-Authored-By: Claude Opus 5.5 --- .../minstrel/cache/sync/SyncControllerTest.kt | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/android/app/src/test/java/com/fabledsword/minstrel/cache/sync/SyncControllerTest.kt b/android/app/src/test/java/com/fabledsword/minstrel/cache/sync/SyncControllerTest.kt index cf26761b..2d2b2665 100644 --- a/android/app/src/test/java/com/fabledsword/minstrel/cache/sync/SyncControllerTest.kt +++ b/android/app/src/test/java/com/fabledsword/minstrel/cache/sync/SyncControllerTest.kt @@ -22,6 +22,7 @@ import org.junit.jupiter.api.Test import retrofit2.Response import retrofit2.Retrofit import kotlin.test.assertEquals +import kotlin.test.assertNull /** * The server returns at most 1000 changes a call (#5654). One page per @@ -38,7 +39,8 @@ class SyncControllerTest { every { sessionCookie } returns MutableStateFlow(null) } private val networkStatus: NetworkStatusController = mockk { - every { state } returns MutableStateFlow(ServerHealth.Healthy) + // Offline, so construction starts no pass; each test runs one itself. + every { state } returns MutableStateFlow(ServerHealth.Offline) } // The cursor round-trips through the DAO, so it is held for real. @@ -59,11 +61,13 @@ class SyncControllerTest { coEvery { api.sync(1000) } returns page(2000, deletedTracks = listOf("merged-away")) coEvery { api.sync(2000) } returns noContent() - SyncController( + val controller = SyncController( metadataDao, mockk(relaxed = true), mockk(relaxed = true), trackDao, authStore, backgroundScope, networkStatus, retrofit, ) - testScheduler.advanceUntilIdle() + controller.syncSafe() + + assertNull(controller.lastSyncError.value) coVerify(exactly = 1) { api.sync(2000) } coVerify { trackDao.deleteByIds(listOf("merged-away")) } @@ -75,11 +79,13 @@ class SyncControllerTest { stored = SyncMetadataEntity(cursor = 500) coEvery { api.sync(500) } returns page(500) - SyncController( + val controller = SyncController( metadataDao, mockk(relaxed = true), mockk(relaxed = true), trackDao, authStore, backgroundScope, networkStatus, retrofit, ) - testScheduler.advanceUntilIdle() + controller.syncSafe() + + assertNull(controller.lastSyncError.value) coVerify(exactly = 1) { api.sync(500) } } @@ -91,11 +97,13 @@ class SyncControllerTest { coEvery { api.sync(0) } returns page(1000) coEvery { api.sync(1000) } returns noContent() - SyncController( + val controller = SyncController( metadataDao, mockk(relaxed = true), mockk(relaxed = true), trackDao, authStore, backgroundScope, networkStatus, retrofit, ) - testScheduler.advanceUntilIdle() + controller.syncSafe() + + assertNull(controller.lastSyncError.value) coVerify(exactly = 1) { api.sync(1000) } assertEquals(1000L, stored?.cursor)