Skip to content

Commit f71dc7b

Browse files
committed
test(PlaceMap): ActionHandler 테스트 작성
`PlaceMapViewModel`의 비대해진 로직을 분리하기 위해 ActionHandler 패턴을 도입하고, 상태 관리 방식을 `StateFlow`로 전면 개편했습니다. - **`PlaceMapViewModel.kt` 리팩토링:** - `PlaceMapHandlerGraph.Factory`를 주입받아 로직을 `SelectActionHandler`, `FilterActionHandler`, `MapEventActionHandler`로 위임하도록 구조를 변경했습니다. - 기존 `LiveData` 기반의 상태 관리를 `StateFlow`(`uiState`)와 `Channel`(`mapControlUiEvent`, `placeMapUiEvent`)로 전환했습니다. - **ActionHandler 테스트 코드 추가:** - `SelectActionHandlerTest`: 플레이스 선택/해제, 상세 정보 조회, 타임태그 클릭 등의 로직 테스트를 작성했습니다. - `FilterActionHandlerTest`: 카테고리 및 타임태그 기반의 장소 필터링 로직 테스트를 작성했습니다. - `MapEventActionHandlerTest`: 지도 초기화, 초기 위치 복귀, 드래그 이벤트 처리 로직 테스트를 작성했습니다. - **테스트 및 유틸리티 정비:** - `PlaceMapViewModelTest`: 핸들러 위임 동작 및 `StateFlow` 상태 변화를 검증하도록 테스트를 수정했습니다. - `PlaceListViewModelTest`를 삭제하고, 관련 픽스처 및 테스트 파일들을 `placeList`에서 `placeMap` 패키지로 이동했습니다. - Flow 기반 테스트를 지원하기 위한 `observeEvent` 확장 함수(`FlowExtensions.kt`)를 추가했습니다.
1 parent d5913f4 commit f71dc7b

File tree

11 files changed

+959
-500
lines changed

11 files changed

+959
-500
lines changed

app/src/main/java/com/daedan/festabook/presentation/placeMap/PlaceMapViewModel.kt

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.daedan.festabook.presentation.placeMap
22

33
import androidx.lifecycle.ViewModel
44
import androidx.lifecycle.viewModelScope
5-
import com.daedan.festabook.di.FestaBookAppGraph
65
import com.daedan.festabook.di.placeMapHandler.PlaceMapHandlerGraph
76
import com.daedan.festabook.di.viewmodel.ViewModelKey
87
import com.daedan.festabook.domain.repository.PlaceListRepository
@@ -22,8 +21,8 @@ import com.daedan.festabook.presentation.placeMap.model.toUiModel
2221
import dev.zacsweers.metro.AppScope
2322
import dev.zacsweers.metro.ContributesIntoMap
2423
import dev.zacsweers.metro.Inject
25-
import dev.zacsweers.metro.asContribution
2624
import kotlinx.coroutines.FlowPreview
25+
import kotlinx.coroutines.channels.BufferOverflow
2726
import kotlinx.coroutines.channels.Channel
2827
import kotlinx.coroutines.flow.Flow
2928
import kotlinx.coroutines.flow.MutableStateFlow
@@ -42,23 +41,28 @@ import kotlinx.coroutines.launch
4241
@Inject
4342
class PlaceMapViewModel(
4443
private val placeListRepository: PlaceListRepository,
45-
appGraph: FestaBookAppGraph,
44+
handlerGraphFactory: PlaceMapHandlerGraph.Factory,
4645
) : ViewModel() {
4746
private val cachedPlaces = MutableStateFlow(listOf<PlaceUiModel>())
4847
private val cachedPlaceByTimeTag = MutableStateFlow<List<PlaceUiModel>>(emptyList())
4948

5049
private val _uiState = MutableStateFlow(PlaceMapUiState())
5150
val uiState: StateFlow<PlaceMapUiState> = _uiState.asStateFlow()
5251

53-
private val _placeMapUiEvent = Channel<PlaceMapEvent>()
52+
private val _placeMapUiEvent =
53+
Channel<PlaceMapEvent>(
54+
onBufferOverflow = BufferOverflow.DROP_OLDEST,
55+
)
5456
val placeMapUiEvent: Flow<PlaceMapEvent> = _placeMapUiEvent.receiveAsFlow()
5557

56-
private val _mapControlUiEvent = Channel<MapControlEvent>()
58+
private val _mapControlUiEvent =
59+
Channel<MapControlEvent>(
60+
onBufferOverflow = BufferOverflow.DROP_OLDEST,
61+
)
5762
val mapControlUiEvent: Flow<MapControlEvent> = _mapControlUiEvent.receiveAsFlow()
5863

5964
private val handlerGraph =
60-
appGraph
61-
.asContribution<PlaceMapHandlerGraph.Factory>()
65+
handlerGraphFactory
6266
.create(
6367
mapControlUiEvent = _mapControlUiEvent,
6468
placeMapUiEvent = _placeMapUiEvent,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package com.daedan.festabook
2+
3+
import kotlinx.coroutines.Deferred
4+
import kotlinx.coroutines.ExperimentalCoroutinesApi
5+
import kotlinx.coroutines.async
6+
import kotlinx.coroutines.flow.Flow
7+
import kotlinx.coroutines.flow.first
8+
import kotlinx.coroutines.test.TestScope
9+
import kotlinx.coroutines.test.advanceUntilIdle
10+
11+
@OptIn(ExperimentalCoroutinesApi::class)
12+
fun <T> TestScope.observeEvent(flow: Flow<T>): Deferred<T> {
13+
val event =
14+
backgroundScope.async {
15+
flow.first()
16+
}
17+
advanceUntilIdle()
18+
return event
19+
}

app/src/test/java/com/daedan/festabook/placeDetail/PlaceDetailTestFixture.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import com.daedan.festabook.domain.model.PlaceDetail
66
import com.daedan.festabook.domain.model.PlaceDetailImage
77
import com.daedan.festabook.domain.model.TimeTag
88
import com.daedan.festabook.news.FAKE_NOTICES
9-
import com.daedan.festabook.placeList.FAKE_PLACES
9+
import com.daedan.festabook.placeMap.FAKE_PLACES
1010
import java.time.LocalTime
1111

1212
val FAKE_PLACE_DETAIL =

app/src/test/java/com/daedan/festabook/placeDetail/PlaceDetailViewModelTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import androidx.arch.core.executor.testing.InstantTaskExecutorRule
44
import com.daedan.festabook.domain.repository.PlaceDetailRepository
55
import com.daedan.festabook.getOrAwaitValue
66
import com.daedan.festabook.news.FAKE_NOTICES
7-
import com.daedan.festabook.placeList.FAKE_PLACES
7+
import com.daedan.festabook.placeMap.FAKE_PLACES
88
import com.daedan.festabook.presentation.news.notice.model.toUiModel
99
import com.daedan.festabook.presentation.placeDetail.PlaceDetailViewModel
1010
import com.daedan.festabook.presentation.placeDetail.model.PlaceDetailUiState

app/src/test/java/com/daedan/festabook/placeList/PlaceListViewModelTest.kt

Lines changed: 0 additions & 161 deletions
This file was deleted.

0 commit comments

Comments
 (0)