@@ -2,12 +2,12 @@ package com.project200.undabang.main
22
33import com.google.common.truth.Truth.assertThat
44import com.project200.common.utils.NetworkMonitor
5- import com.project200.domain.model.BaseResult
5+ import com.project200.domain.model.FcmTokenSyncResult
66import com.project200.domain.model.UpdateCheckResult
77import com.project200.domain.usecase.CheckForUpdateUseCase
88import com.project200.domain.usecase.ClearSessionUseCase
99import com.project200.domain.usecase.GetMemberIdUseCase
10- import com.project200.domain.usecase.LoginUseCase
10+ import com.project200.domain.usecase.SyncFcmTokenUseCase
1111import com.project200.undabang.oauth.AuthManager
1212import com.project200.undabang.oauth.AuthStateManager
1313import com.project200.undabang.oauth.TokenRefreshResult
@@ -43,7 +43,7 @@ class MainViewModelTest {
4343 private lateinit var mockCheckForUpdateUseCase: CheckForUpdateUseCase
4444
4545 @MockK
46- private lateinit var mockLoginUseCase : LoginUseCase
46+ private lateinit var mockSyncFcmTokenUseCase : SyncFcmTokenUseCase
4747
4848 @MockK
4949 private lateinit var mockNetworkMonitor: NetworkMonitor
@@ -85,7 +85,7 @@ class MainViewModelTest {
8585 private fun createViewModel (): MainViewModel {
8686 return MainViewModel (
8787 checkForUpdateUseCase = mockCheckForUpdateUseCase,
88- loginUseCase = mockLoginUseCase ,
88+ syncFcmTokenUseCase = mockSyncFcmTokenUseCase ,
8989 networkMonitor = mockNetworkMonitor,
9090 authManager = mockAuthManager,
9191 authStateManager = mockAuthStateManager,
@@ -122,7 +122,7 @@ class MainViewModelTest {
122122 // Given
123123 stubNoUpdate()
124124 stubAuthState(isAuthorized = true , needsRefresh = false )
125- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
125+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
126126
127127 // When: init이 진입을 시작한다 — 별도 호출 없음
128128 viewModel = createViewModel()
@@ -131,7 +131,7 @@ class MainViewModelTest {
131131 // Then
132132 assertThat(viewModel.entryState.value).isEqualTo(EntryState .Content )
133133 coVerify(exactly = 1 ) { mockCheckForUpdateUseCase() }
134- coVerify(exactly = 1 ) { mockLoginUseCase () }
134+ coVerify(exactly = 1 ) { mockSyncFcmTokenUseCase () }
135135 }
136136
137137 @Test
@@ -147,7 +147,7 @@ class MainViewModelTest {
147147
148148 // Then
149149 assertThat(viewModel.entryState.value).isEqualTo(EntryState .Login )
150- coVerify(exactly = 0 ) { mockLoginUseCase () }
150+ coVerify(exactly = 0 ) { mockSyncFcmTokenUseCase () }
151151 }
152152
153153 @Test
@@ -157,7 +157,7 @@ class MainViewModelTest {
157157 stubNoUpdate()
158158 stubAuthState(isAuthorized = true , needsRefresh = true )
159159 coEvery { mockAuthManager.refreshAccessToken() } returns TokenRefreshResult .Success (mockk())
160- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
160+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
161161
162162 // When
163163 viewModel = createViewModel()
@@ -182,7 +182,7 @@ class MainViewModelTest {
182182
183183 // Then
184184 assertThat(viewModel.entryState.value).isEqualTo(EntryState .Login )
185- coVerify(exactly = 0 ) { mockLoginUseCase () }
185+ coVerify(exactly = 0 ) { mockSyncFcmTokenUseCase () }
186186 }
187187
188188 @Test
@@ -193,7 +193,7 @@ class MainViewModelTest {
193193 stubAuthState(isAuthorized = true , needsRefresh = true )
194194 coEvery { mockAuthManager.refreshAccessToken() } returns
195195 TokenRefreshResult .Error (AuthorizationException .GeneralErrors .NETWORK_ERROR )
196- coEvery { mockLoginUseCase () } returns BaseResult . Error ( " NETWORK_ERROR " , " 오프라인 " )
196+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . FAILURE
197197
198198 // When
199199 viewModel = createViewModel()
@@ -232,7 +232,7 @@ class MainViewModelTest {
232232
233233 // Then
234234 assertThat(viewModel.entryState.value).isEqualTo(EntryState .Login )
235- coVerify(exactly = 0 ) { mockLoginUseCase () }
235+ coVerify(exactly = 0 ) { mockSyncFcmTokenUseCase () }
236236 }
237237
238238 @Test
@@ -265,7 +265,7 @@ class MainViewModelTest {
265265
266266 // Then: 게이트 닫힘 — 토큰 판정·FCM 등록 미진행
267267 assertThat(viewModel.entryState.value).isEqualTo(EntryState .ForceUpdate (fromReconnect = false ))
268- coVerify(exactly = 0 ) { mockLoginUseCase () }
268+ coVerify(exactly = 0 ) { mockSyncFcmTokenUseCase () }
269269 }
270270
271271 @Test
@@ -275,7 +275,7 @@ class MainViewModelTest {
275275 coEvery { mockCheckForUpdateUseCase() } returns
276276 Result .success(UpdateCheckResult .UpdateAvailable (isForceUpdate = false ))
277277 stubAuthState(isAuthorized = true )
278- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
278+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
279279
280280 // When
281281 viewModel = createViewModel()
@@ -296,7 +296,7 @@ class MainViewModelTest {
296296 // Given
297297 coEvery { mockCheckForUpdateUseCase() } returns Result .failure(Exception (" Network error" ))
298298 stubAuthState(isAuthorized = true )
299- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
299+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
300300
301301 // When
302302 viewModel = createViewModel()
@@ -314,7 +314,7 @@ class MainViewModelTest {
314314 // Given: 정상 진입 완료
315315 stubNoUpdate()
316316 stubAuthState(isAuthorized = true )
317- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
317+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
318318 viewModel = createViewModel()
319319 testDispatcher.scheduler.advanceUntilIdle()
320320 assertThat(viewModel.entryState.value).isEqualTo(EntryState .Content )
@@ -337,7 +337,7 @@ class MainViewModelTest {
337337 forceLogoutFlow.emit(Unit ) // 갱신 도중 강제 로그아웃 발생
338338 TokenRefreshResult .Error (AuthorizationException .GeneralErrors .NETWORK_ERROR ) // 진입은 오프라인 경로로 완주 시도
339339 }
340- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
340+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
341341
342342 // When
343343 viewModel = createViewModel()
@@ -356,7 +356,7 @@ class MainViewModelTest {
356356 every { mockNetworkMonitor.isCurrentlyConnected() } returns false
357357 stubNoUpdate()
358358 stubAuthState(isAuthorized = true )
359- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
359+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
360360 viewModel = createViewModel()
361361 testDispatcher.scheduler.advanceUntilIdle()
362362
@@ -374,7 +374,7 @@ class MainViewModelTest {
374374 // Given: 온라인 시작(setUp 기본값)으로 Content 진입
375375 stubNoUpdate()
376376 stubAuthState(isAuthorized = true )
377- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
377+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
378378 viewModel = createViewModel()
379379 testDispatcher.scheduler.advanceUntilIdle()
380380
@@ -419,7 +419,7 @@ class MainViewModelTest {
419419 Result .success(UpdateCheckResult .NoUpdateNeeded ) andThen
420420 Result .success(UpdateCheckResult .UpdateAvailable (isForceUpdate = true ))
421421 stubAuthState(isAuthorized = true )
422- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
422+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
423423 viewModel = createViewModel()
424424 testDispatcher.scheduler.advanceUntilIdle()
425425
@@ -440,7 +440,7 @@ class MainViewModelTest {
440440 Result .success(UpdateCheckResult .NoUpdateNeeded ) andThen
441441 Result .failure(Exception (" Network error" ))
442442 stubAuthState(isAuthorized = true )
443- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
443+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
444444 viewModel = createViewModel()
445445 testDispatcher.scheduler.advanceUntilIdle()
446446
@@ -461,9 +461,9 @@ class MainViewModelTest {
461461 // Given: 처음엔 실패, 이후엔 성공
462462 stubNoUpdate()
463463 stubAuthState(isAuthorized = true )
464- coEvery { mockLoginUseCase () } returns
465- BaseResult . Error ( " NETWORK_ERROR " , " 네트워크 오류 " ) andThen
466- BaseResult . Success ( Unit )
464+ coEvery { mockSyncFcmTokenUseCase () } returns
465+ FcmTokenSyncResult . FAILURE andThen
466+ FcmTokenSyncResult . SUCCESS
467467 viewModel = createViewModel()
468468 testDispatcher.scheduler.advanceUntilIdle()
469469
@@ -473,7 +473,7 @@ class MainViewModelTest {
473473 testDispatcher.scheduler.advanceUntilIdle()
474474
475475 // Then: 진입 1회 + 재시도 1회
476- coVerify(exactly = 2 ) { mockLoginUseCase () }
476+ coVerify(exactly = 2 ) { mockSyncFcmTokenUseCase () }
477477 }
478478
479479 @Test
@@ -482,7 +482,7 @@ class MainViewModelTest {
482482 // Given
483483 stubNoUpdate()
484484 stubAuthState(isAuthorized = true )
485- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
485+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
486486 viewModel = createViewModel()
487487 testDispatcher.scheduler.advanceUntilIdle()
488488
@@ -492,18 +492,18 @@ class MainViewModelTest {
492492 testDispatcher.scheduler.advanceUntilIdle()
493493
494494 // Then: 진입 1회뿐
495- coVerify(exactly = 1 ) { mockLoginUseCase () }
495+ coVerify(exactly = 1 ) { mockSyncFcmTokenUseCase () }
496496 }
497497
498498 @Test
499- fun `FCM 등록 - 토큰이 없어 실패하면 대기가 닫히지 않고 재연결 때 재시도한다` () =
499+ fun `FCM 등록 - 보낼 토큰이 없으면 대기가 닫히지 않고 재연결 때 재시도한다` () =
500500 runTest {
501- // Given: FCM 토큰이 없어 서버 로그인이 막힌다
501+ // Given: 저장된 토큰이 없어 SKIPPED로 끝난다. 그사이 토큰이 도착하면 다음엔 성공한다
502502 stubNoUpdate()
503503 stubAuthState(isAuthorized = true )
504- coEvery { mockLoginUseCase () } returns
505- BaseResult . Error ( " NO_FCM_TOKEN " , " FCM 토큰이 없어 서버 로그인을 보내지 않았습니다. " ) andThen
506- BaseResult . Success ( Unit )
504+ coEvery { mockSyncFcmTokenUseCase () } returns
505+ FcmTokenSyncResult . SKIPPED andThen
506+ FcmTokenSyncResult . SUCCESS
507507 viewModel = createViewModel()
508508 testDispatcher.scheduler.advanceUntilIdle()
509509
@@ -512,8 +512,8 @@ class MainViewModelTest {
512512 networkStateFlow.emit(true )
513513 testDispatcher.scheduler.advanceUntilIdle()
514514
515- // Then: 성공으로 닫히지 않았으므로 재시도가 한 번 더 나간다
516- coVerify(exactly = 2 ) { mockLoginUseCase () }
515+ // Then: SKIPPED는 성공이 아니므로 대기가 열려 있고 재시도가 나간다
516+ coVerify(exactly = 2 ) { mockSyncFcmTokenUseCase () }
517517 }
518518
519519 @Test
@@ -522,9 +522,9 @@ class MainViewModelTest {
522522 // Given: 등록 요청이 느리게 진행 중
523523 stubNoUpdate()
524524 stubAuthState(isAuthorized = true )
525- coEvery { mockLoginUseCase () } coAnswers {
525+ coEvery { mockSyncFcmTokenUseCase () } coAnswers {
526526 delay(10_000 ) // 응답 지연 — 이 사이 재연결이 겹친다
527- BaseResult . Error ( " NETWORK_ERROR " , " 타임아웃 " )
527+ FcmTokenSyncResult . FAILURE
528528 }
529529 viewModel = createViewModel()
530530 testDispatcher.scheduler.runCurrent() // 진입 시작 → 등록 요청 발사(지연 중)
@@ -535,7 +535,7 @@ class MainViewModelTest {
535535 testDispatcher.scheduler.runCurrent()
536536
537537 // Then: 실행 중 가드(registrationJob.isActive)가 두 번째 발사를 막는다
538- coVerify(exactly = 1 ) { mockLoginUseCase () }
538+ coVerify(exactly = 1 ) { mockSyncFcmTokenUseCase () }
539539 }
540540
541541 @Test
@@ -544,7 +544,7 @@ class MainViewModelTest {
544544 // Given
545545 stubNoUpdate()
546546 stubAuthState(isAuthorized = true )
547- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
547+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
548548 every { mockNetworkMonitor.isCurrentlyConnected() } returns true
549549 viewModel = createViewModel()
550550 testDispatcher.scheduler.advanceUntilIdle()
@@ -559,7 +559,7 @@ class MainViewModelTest {
559559 // Given
560560 stubNoUpdate()
561561 stubAuthState(isAuthorized = true )
562- coEvery { mockLoginUseCase () } returns BaseResult . Success ( Unit )
562+ coEvery { mockSyncFcmTokenUseCase () } returns FcmTokenSyncResult . SUCCESS
563563 every { mockNetworkMonitor.isCurrentlyConnected() } returns false
564564 viewModel = createViewModel()
565565 testDispatcher.scheduler.advanceUntilIdle()
0 commit comments