feat(audio-recommendation): 추천 snapshot 갱신 서비스를 추가한다

This commit is contained in:
2026-06-23 21:05:26 +09:00
parent 70346b911f
commit 1c7bac3a73
2 changed files with 220 additions and 0 deletions
@@ -0,0 +1,84 @@
package kr.co.vividnext.sodalive.v2.audio.recommendation.application
import kr.co.vividnext.sodalive.v2.audio.recommendation.domain.AudioRecommendationVisibility
import kr.co.vividnext.sodalive.v2.audio.recommendation.port.out.AudioRecommendationQueryPort
import kr.co.vividnext.sodalive.v2.recommendation.domain.RecommendedSectionType
import kr.co.vividnext.sodalive.v2.recommendation.port.out.RecommendationSnapshotPort
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.mockito.Mockito
import java.time.LocalDateTime
import java.time.ZoneId
import java.time.ZonedDateTime
class AudioRecommendationSnapshotRefreshServiceTest {
private val snapshotPort = Mockito.mock(RecommendationSnapshotPort::class.java)
private val queryPort = Mockito.mock(AudioRecommendationQueryPort::class.java)
private val service = AudioRecommendationSnapshotRefreshService(snapshotPort, queryPort)
@Test
@DisplayName("일 배치는 KST 전날 23:59:59 기준으로 여섯 오디오 스냅샷을 교체한다")
fun shouldRefreshAllAudioSnapshotsWithKstPreviousDaySnapshotAt() {
val now = LocalDateTime.of(2026, 6, 24, 0, 0)
val snapshotAt = LocalDateTime.of(2026, 6, 23, 23, 59, 59)
val newAndHotWindowStart = LocalDateTime.of(2026, 6, 21, 0, 0)
val mostCommentedWindowStart = LocalDateTime.of(2026, 6, 17, 0, 0)
service.refreshDailySnapshots(now)
Mockito.verify(queryPort).findNewAndHotSnapshots(
newAndHotWindowStart,
snapshotAt,
AudioRecommendationVisibility.SAFE,
AudioRecommendationSnapshotRefreshService.NEW_AND_HOT_LIMIT
)
Mockito.verify(queryPort).findMostCommentedSnapshots(
mostCommentedWindowStart,
snapshotAt,
AudioRecommendationVisibility.ALL,
AudioRecommendationSnapshotRefreshService.MOST_COMMENTED_LIMIT
)
Mockito.verify(queryPort).findRecommendedAudioSnapshots(
mostCommentedWindowStart,
snapshotAt,
AudioRecommendationVisibility.SAFE,
AudioRecommendationSnapshotRefreshService.RECOMMENDED_AUDIO_LIMIT
)
Mockito.verify(snapshotPort).replaceSnapshots(RecommendedSectionType.NEW_AND_HOT_AUDIO_SAFE, snapshotAt, emptyList())
Mockito.verify(snapshotPort).replaceSnapshots(RecommendedSectionType.NEW_AND_HOT_AUDIO_ALL, snapshotAt, emptyList())
Mockito.verify(snapshotPort).replaceSnapshots(RecommendedSectionType.MOST_COMMENTED_AUDIO_SAFE, snapshotAt, emptyList())
Mockito.verify(snapshotPort).replaceSnapshots(RecommendedSectionType.MOST_COMMENTED_AUDIO_ALL, snapshotAt, emptyList())
Mockito.verify(snapshotPort).replaceSnapshots(RecommendedSectionType.RECOMMENDED_AUDIO_SAFE, snapshotAt, emptyList())
Mockito.verify(snapshotPort).replaceSnapshots(RecommendedSectionType.RECOMMENDED_AUDIO_ALL, snapshotAt, emptyList())
}
@Test
@DisplayName("일 배치는 ZonedDateTime 입력의 zone과 무관하게 KST 날짜 경계 기준으로 스냅샷 시각을 계산한다")
fun shouldRefreshSnapshotsByKstBoundaryFromZonedDateTime() {
val now = ZonedDateTime.of(2026, 6, 24, 0, 0, 0, 0, ZoneId.of("Asia/Seoul"))
val snapshotAt = LocalDateTime.of(2026, 6, 23, 23, 59, 59)
val newAndHotWindowStart = LocalDateTime.of(2026, 6, 21, 0, 0)
val mostCommentedWindowStart = LocalDateTime.of(2026, 6, 17, 0, 0)
service.refreshDailySnapshots(now)
Mockito.verify(queryPort).findNewAndHotSnapshots(
newAndHotWindowStart,
snapshotAt,
AudioRecommendationVisibility.SAFE,
AudioRecommendationSnapshotRefreshService.NEW_AND_HOT_LIMIT
)
Mockito.verify(queryPort).findMostCommentedSnapshots(
mostCommentedWindowStart,
snapshotAt,
AudioRecommendationVisibility.ALL,
AudioRecommendationSnapshotRefreshService.MOST_COMMENTED_LIMIT
)
Mockito.verify(queryPort).findRecommendedAudioSnapshots(
mostCommentedWindowStart,
snapshotAt,
AudioRecommendationVisibility.SAFE,
AudioRecommendationSnapshotRefreshService.RECOMMENDED_AUDIO_LIMIT
)
}
}