feat(content-preference): 콘텐츠 조회 설정 서버 저장 전환을 반영한다

This commit is contained in:
2026-03-27 13:33:51 +09:00
parent 1ba3cb8a40
commit a87bd147dc
75 changed files with 3593 additions and 301 deletions

View File

@@ -0,0 +1,130 @@
package kr.co.vividnext.sodalive.member
import kr.co.vividnext.sodalive.common.SodaException
import kr.co.vividnext.sodalive.content.ContentType
import kr.co.vividnext.sodalive.i18n.LangContext
import kr.co.vividnext.sodalive.i18n.SodaMessageSource
import kr.co.vividnext.sodalive.marketing.AdTrackingService
import kr.co.vividnext.sodalive.member.contentpreference.MemberContentPreferenceService
import kr.co.vividnext.sodalive.member.contentpreference.UpdateMemberContentPreferenceRequest
import kr.co.vividnext.sodalive.member.contentpreference.ViewerContentPreference
import kr.co.vividnext.sodalive.member.social.SocialAuthServiceResolver
import kr.co.vividnext.sodalive.useraction.UserActionService
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertThrows
import org.junit.jupiter.api.Assertions.assertTrue
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.mockito.Mockito
class MemberControllerTest {
private lateinit var memberService: MemberService
private lateinit var memberContentPreferenceService: MemberContentPreferenceService
private lateinit var socialAuthServiceResolver: SocialAuthServiceResolver
private lateinit var trackingService: AdTrackingService
private lateinit var userActionService: UserActionService
private lateinit var controller: MemberController
@BeforeEach
fun setup() {
memberService = mock()
memberContentPreferenceService = mock()
socialAuthServiceResolver = mock()
trackingService = mock()
userActionService = mock()
controller = MemberController(
service = memberService,
memberContentPreferenceService = memberContentPreferenceService,
socialAuthServiceResolver = socialAuthServiceResolver,
trackingService = trackingService,
userActionService = userActionService,
messageSource = SodaMessageSource(),
langContext = LangContext()
)
}
@Test
@DisplayName("PATCH /member/content-preference는 저장된 최신 설정을 응답한다")
fun shouldReturnUpdatedPreferenceWhenRequestIsValid() {
val member = createMember(1L)
val request = UpdateMemberContentPreferenceRequest(
isAdultContentVisible = true,
contentType = ContentType.FEMALE
)
val viewerPreference = ViewerContentPreference(
countryCode = "KR",
isAdultContentVisible = true,
contentType = ContentType.FEMALE,
isAdult = true
)
Mockito.`when`(
memberContentPreferenceService.updatePreference(
member = member,
isAdultContentVisible = true,
contentType = ContentType.FEMALE
)
).thenReturn(viewerPreference)
val response = controller.updateContentPreference(request, member)
assertTrue(response.success)
assertEquals(true, response.data?.isAdultContentVisible)
assertEquals(ContentType.FEMALE, response.data?.contentType)
}
@Test
@DisplayName("비로그인 사용자는 PATCH /member/content-preference 호출 시 예외가 발생한다")
fun shouldThrowWhenMemberIsNullOnUpdateContentPreference() {
val request = UpdateMemberContentPreferenceRequest(
isAdultContentVisible = true,
contentType = ContentType.ALL
)
val exception = assertThrows(SodaException::class.java) {
controller.updateContentPreference(request, null)
}
assertEquals("common.error.bad_credentials", exception.messageKey)
Mockito.verifyNoInteractions(memberContentPreferenceService)
}
@Test
@DisplayName("두 필드 모두 누락된 PATCH 요청은 서비스 예외를 그대로 전파한다")
fun shouldPropagateServiceExceptionWhenBothFieldsAreMissing() {
val member = createMember(2L)
val request = UpdateMemberContentPreferenceRequest(
isAdultContentVisible = null,
contentType = null
)
Mockito.`when`(
memberContentPreferenceService.updatePreference(
member = member,
isAdultContentVisible = null,
contentType = null
)
).thenThrow(SodaException(messageKey = "common.error.invalid_request"))
val exception = assertThrows(SodaException::class.java) {
controller.updateContentPreference(request, member)
}
assertEquals("common.error.invalid_request", exception.messageKey)
}
private fun createMember(id: Long): Member {
val member = Member(
email = "member$id@test.com",
password = "password",
nickname = "member$id"
)
member.id = id
return member
}
private inline fun <reified T> mock(): T {
return Mockito.mock(T::class.java)
}
}