fix(content-preference): 멤버 콘텐츠 선호 신규 생성 정책을 저장값 기준으로 정리한다
This commit is contained in:
@@ -47,8 +47,8 @@ class MemberContentPreferenceIntegrationTest @Autowired constructor(
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("legacy 파라미터 최초 호출 시 row를 생성하고 같은 흐름에서 저장값 조회에 즉시 반영한다")
|
||||
fun shouldCreateRowAndReflectImmediatelyOnFirstLegacyResolveCall() {
|
||||
@DisplayName("미인증 사용자는 row 미존재 시 legacy 파라미터와 무관하게 false/ALL로 생성한다")
|
||||
fun shouldCreateDefaultPreferenceForUnauthenticatedMemberRegardlessOfLegacyParams() {
|
||||
val member = saveNonForcedMember("legacy-user")
|
||||
countryContext.setCountryCode("US")
|
||||
|
||||
@@ -61,12 +61,39 @@ class MemberContentPreferenceIntegrationTest @Autowired constructor(
|
||||
)
|
||||
val stored = service.getStoredPreference(member)
|
||||
|
||||
assertNotNull(preferenceRepository.findByMemberId(member.id!!))
|
||||
assertFalse(resolved.isAdultContentVisible)
|
||||
assertEquals(ContentType.ALL, resolved.contentType)
|
||||
assertEquals("US", resolved.countryCode)
|
||||
assertFalse(stored.isAdultContentVisible)
|
||||
assertEquals(ContentType.ALL, stored.contentType)
|
||||
assertFalse(stored.isAdult)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("인증 사용자는 row 미존재 + legacy 파라미터 미전달 시 true/ALL로 생성된다")
|
||||
fun shouldCreateTrueAndAllWhenAuthenticatedMemberHasNoLegacyParams() {
|
||||
val member = saveNonForcedMember("auth-no-legacy")
|
||||
countryContext.setCountryCode("US")
|
||||
saveAuth(member)
|
||||
|
||||
val reloadedMember = memberRepository.findById(member.id!!).orElseThrow()
|
||||
|
||||
assertEquals(null, preferenceRepository.findByMemberId(member.id!!))
|
||||
|
||||
val resolved = service.resolveForQuery(
|
||||
member = reloadedMember,
|
||||
isAdultContentVisible = null,
|
||||
contentType = null
|
||||
)
|
||||
val stored = service.getStoredPreference(reloadedMember)
|
||||
|
||||
assertNotNull(preferenceRepository.findByMemberId(member.id!!))
|
||||
assertTrue(resolved.isAdultContentVisible)
|
||||
assertEquals(ContentType.MALE, resolved.contentType)
|
||||
assertEquals(ContentType.ALL, resolved.contentType)
|
||||
assertEquals("US", resolved.countryCode)
|
||||
assertTrue(stored.isAdultContentVisible)
|
||||
assertEquals(ContentType.MALE, stored.contentType)
|
||||
assertEquals(ContentType.ALL, stored.contentType)
|
||||
assertTrue(stored.isAdult)
|
||||
}
|
||||
|
||||
@@ -131,6 +158,33 @@ class MemberContentPreferenceIntegrationTest @Autowired constructor(
|
||||
assertTrue(resolved.isAdult)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("기존 row가 있으면 legacy 파라미터를 보내도 저장값을 그대로 사용한다")
|
||||
fun shouldIgnoreLegacyParamsWhenPreferenceAlreadyExists() {
|
||||
val member = saveNonForcedMember("existing-pref")
|
||||
countryContext.setCountryCode("US")
|
||||
saveAuth(member)
|
||||
|
||||
val reloadedMember = memberRepository.findById(member.id!!).orElseThrow()
|
||||
service.updatePreference(
|
||||
member = reloadedMember,
|
||||
isAdultContentVisible = false,
|
||||
contentType = ContentType.FEMALE
|
||||
)
|
||||
|
||||
val resolved = service.resolveForQuery(
|
||||
member = reloadedMember,
|
||||
isAdultContentVisible = true,
|
||||
contentType = ContentType.MALE
|
||||
)
|
||||
val stored = service.getStoredPreference(reloadedMember)
|
||||
|
||||
assertFalse(resolved.isAdultContentVisible)
|
||||
assertEquals(ContentType.FEMALE, resolved.contentType)
|
||||
assertFalse(stored.isAdultContentVisible)
|
||||
assertEquals(ContentType.FEMALE, stored.contentType)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("authVerify 성공 후 markAdultVisibleAfterAuthVerify를 호출하면 저장값이 true로 반영된다")
|
||||
fun shouldMarkAdultVisibleAfterAuthVerify() {
|
||||
|
||||
@@ -257,6 +257,75 @@ class MemberContentPreferenceServiceTest {
|
||||
Mockito.verify(repository).saveAndFlush(Mockito.any(MemberContentPreference::class.java))
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("row 미존재 + 인증 사용자의 legacy 조회 파라미터는 초기 생성값으로 반영된다")
|
||||
fun shouldSeedPreferenceFromLegacyParamsWhenRowMissingAndAuthenticated() {
|
||||
val member = createMember(id = 2100L, withAuth = true)
|
||||
countryContext.setCountryCode("US")
|
||||
|
||||
Mockito.`when`(repository.findByMemberId(2100L)).thenReturn(null)
|
||||
Mockito.`when`(memberRepository.findByIdForUpdate(2100L)).thenReturn(member)
|
||||
Mockito.`when`(repository.findByMemberIdForUpdate(2100L)).thenReturn(null)
|
||||
Mockito.`when`(repository.saveAndFlush(Mockito.any(MemberContentPreference::class.java)))
|
||||
.thenAnswer { invocation -> invocation.getArgument(0) }
|
||||
|
||||
val result = service.resolveForQuery(
|
||||
member = member,
|
||||
isAdultContentVisible = true,
|
||||
contentType = ContentType.FEMALE
|
||||
)
|
||||
|
||||
assertTrue(result.isAdultContentVisible)
|
||||
assertEquals(ContentType.FEMALE, result.contentType)
|
||||
assertTrue(result.isAdult)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("row 미존재 + 인증 사용자는 legacy 파라미터가 없으면 true/ALL로 초기 생성된다")
|
||||
fun shouldSeedPreferenceToTrueAndAllWhenRowMissingAndAuthenticatedWithoutParams() {
|
||||
val member = createMember(id = 2101L, withAuth = true)
|
||||
countryContext.setCountryCode("US")
|
||||
|
||||
Mockito.`when`(repository.findByMemberId(2101L)).thenReturn(null)
|
||||
Mockito.`when`(memberRepository.findByIdForUpdate(2101L)).thenReturn(member)
|
||||
Mockito.`when`(repository.findByMemberIdForUpdate(2101L)).thenReturn(null)
|
||||
Mockito.`when`(repository.saveAndFlush(Mockito.any(MemberContentPreference::class.java)))
|
||||
.thenAnswer { invocation -> invocation.getArgument(0) }
|
||||
|
||||
val result = service.resolveForQuery(
|
||||
member = member,
|
||||
isAdultContentVisible = null,
|
||||
contentType = null
|
||||
)
|
||||
|
||||
assertTrue(result.isAdultContentVisible)
|
||||
assertEquals(ContentType.ALL, result.contentType)
|
||||
assertTrue(result.isAdult)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("row 미존재 + 미인증 사용자는 legacy 파라미터와 무관하게 false/ALL로 초기 생성된다")
|
||||
fun shouldSeedPreferenceToFalseAndAllWhenRowMissingAndUnauthenticated() {
|
||||
val member = createMember(id = 2102L)
|
||||
countryContext.setCountryCode("US")
|
||||
|
||||
Mockito.`when`(repository.findByMemberId(2102L)).thenReturn(null)
|
||||
Mockito.`when`(memberRepository.findByIdForUpdate(2102L)).thenReturn(member)
|
||||
Mockito.`when`(repository.findByMemberIdForUpdate(2102L)).thenReturn(null)
|
||||
Mockito.`when`(repository.saveAndFlush(Mockito.any(MemberContentPreference::class.java)))
|
||||
.thenAnswer { invocation -> invocation.getArgument(0) }
|
||||
|
||||
val result = service.resolveForQuery(
|
||||
member = member,
|
||||
isAdultContentVisible = true,
|
||||
contentType = ContentType.MALE
|
||||
)
|
||||
|
||||
assertFalse(result.isAdultContentVisible)
|
||||
assertEquals(ContentType.ALL, result.contentType)
|
||||
assertFalse(result.isAdult)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("초기 row 생성 경쟁 시 잠금 이후 재조회한 row를 반환한다")
|
||||
fun shouldReturnReloadedPreferenceWhenRowIsCreatedByAnotherTransactionAfterLock() {
|
||||
@@ -349,8 +418,8 @@ class MemberContentPreferenceServiceTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("contentType 미전달 조회는 기존 contentType을 유지한다")
|
||||
fun shouldKeepStoredContentTypeWhenContentTypeIsNotProvided() {
|
||||
@DisplayName("기존 row가 있으면 legacy 조회 파라미터를 무시하고 저장값을 그대로 사용한다")
|
||||
fun shouldIgnoreLegacyParamsWhenPreferenceAlreadyExists() {
|
||||
val member = createMember(id = 21L, withAuth = true)
|
||||
val preference = MemberContentPreference(
|
||||
isAdultContentVisible = false,
|
||||
@@ -365,16 +434,16 @@ class MemberContentPreferenceServiceTest {
|
||||
val result = service.resolveForQuery(
|
||||
member = member,
|
||||
isAdultContentVisible = true,
|
||||
contentType = null
|
||||
contentType = ContentType.MALE
|
||||
)
|
||||
|
||||
assertEquals(ContentType.FEMALE, result.contentType)
|
||||
assertTrue(result.isAdultContentVisible)
|
||||
assertFalse(result.isAdultContentVisible)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("legacy 조회 파라미터로 저장값이 바뀌면 추천 라이브 캐시를 무효화한다")
|
||||
fun shouldEvictRecommendLiveCacheWhenPreferenceChangesByLegacyResolveForQuery() {
|
||||
@DisplayName("기존 row가 있으면 legacy 조회 파라미터로 캐시를 무효화하지 않는다")
|
||||
fun shouldNotEvictRecommendLiveCacheWhenLegacyResolveForQueryIsIgnored() {
|
||||
val member = createMember(id = 25L, withAuth = true)
|
||||
val preference = createPreference(member)
|
||||
countryContext.setCountryCode("US")
|
||||
@@ -386,7 +455,7 @@ class MemberContentPreferenceServiceTest {
|
||||
contentType = null
|
||||
)
|
||||
|
||||
verifyRecommendLiveCacheEvicted(25L)
|
||||
verifyRecommendLiveCacheNotEvicted(25L)
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user