package kr.co.vividnext.sodalive.content import kr.co.vividnext.sodalive.i18n.translation.DetectedLanguage import kr.co.vividnext.sodalive.i18n.translation.LanguageDetectionProvider import kr.co.vividnext.sodalive.i18n.translation.LanguageProviderId import kr.co.vividnext.sodalive.i18n.translation.LanguageProviderProperties import kr.co.vividnext.sodalive.i18n.translation.SourceTextNormalizer import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Test import org.mockito.Mockito class LanguageDetectionCacheServiceTest { @Test fun shouldReuseCachedLanguageDetectionForSameNormalizedText() { val repository = Mockito.mock(LanguageDetectionResultRepository::class.java) var providerCalls = 0 val service = service(repository) { providerCalls++; "ko" } val sourceHash = SourceTextNormalizer.hash("Hello world") Mockito.`when`( repository.findBySourceHashAndProviderAndNormalizationVersion( sourceHash = sourceHash, provider = "papago", normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) ).thenReturn( LanguageDetectionResult( sourceHash = sourceHash, sourceTextSample = "Hello world", detectedLanguage = "en", provider = "papago", confidence = null, normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) ) val detected = service.detectWithCache("Hello world") assertEquals(DetectedLanguage("en", LanguageProviderId.PAPAGO), detected) assertEquals(0, providerCalls) Mockito.verify(repository).findBySourceHashAndProviderAndNormalizationVersion( sourceHash = sourceHash, provider = "papago", normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) Mockito.verifyNoMoreInteractions(repository) } @Test @DisplayName("최초 캐시 저장 경합에서는 저장된 승자의 감지 언어를 반환한다") fun shouldReturnStoredWinnerAfterInitialCacheInsert() { val repository = Mockito.mock(LanguageDetectionResultRepository::class.java) val service = service(repository) { "en" } val sourceHash = SourceTextNormalizer.hash("Hello world") Mockito.`when`( repository.findBySourceHashAndProviderAndNormalizationVersion( sourceHash = sourceHash, provider = "papago", normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) ).thenReturn(null) Mockito.`when`( repository.insertIfAbsent( sourceHash = sourceHash, sourceTextSample = "Hello world", detectedLanguage = "en", provider = "papago", confidence = null, normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) ).thenReturn(0) Mockito.`when`( repository.findDetectedLanguageForUpdate( sourceHash = sourceHash, provider = "papago", normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) ).thenReturn("ko") val detected = service.detectWithCache("Hello world") assertEquals(DetectedLanguage("ko", LanguageProviderId.PAPAGO), detected) Mockito.verify(repository).findBySourceHashAndProviderAndNormalizationVersion( sourceHash = sourceHash, provider = "papago", normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) Mockito.verify(repository).insertIfAbsent( sourceHash = sourceHash, sourceTextSample = "Hello world", detectedLanguage = "en", provider = "papago", confidence = null, normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) Mockito.verify(repository).findDetectedLanguageForUpdate( sourceHash = sourceHash, provider = "papago", normalizationVersion = SourceTextNormalizer.NORMALIZATION_VERSION ) Mockito.verifyNoMoreInteractions(repository) } private fun service(repository: LanguageDetectionResultRepository, detect: () -> String?): LanguageDetectionCacheService { val provider = object : LanguageDetectionProvider { override val providerId = LanguageProviderId.PAPAGO override fun detect(query: String) = detect() } return LanguageDetectionCacheService(repository, listOf(provider), LanguageProviderProperties()) } }