From 036cd4053948481e3d4cbc372b8d15f363ee60ca Mon Sep 17 00:00:00 2001 From: Klaus Date: Mon, 29 Jun 2026 11:24:21 +0900 Subject: [PATCH] =?UTF-8?q?fix(chat):=20=EB=B0=B0=EB=84=88=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=9D=91=EB=8B=B5=20=EC=83=9D=EC=84=B1=EC=9D=84=20?= =?UTF-8?q?=EC=84=9C=EB=B9=84=EC=8A=A4=EB=A1=9C=20=EC=98=AE=EA=B8=B4?= =?UTF-8?q?=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/ChatCharacterBannerService.kt | 17 ++++- ...atCharacterBannerServiceIntegrationTest.kt | 76 +++++++++++++++++++ 2 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src/test/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerServiceIntegrationTest.kt diff --git a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerService.kt b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerService.kt index 40858642..43968c0d 100644 --- a/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerService.kt +++ b/src/main/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerService.kt @@ -1,5 +1,7 @@ package kr.co.vividnext.sodalive.chat.character.service +import kr.co.vividnext.sodalive.admin.chat.dto.ChatCharacterBannerListPageResponse +import kr.co.vividnext.sodalive.admin.chat.dto.ChatCharacterBannerResponse import kr.co.vividnext.sodalive.chat.character.ChatCharacterBanner import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterBannerRepository import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository @@ -11,6 +13,7 @@ import org.springframework.stereotype.Service import org.springframework.transaction.annotation.Transactional @Service +@Transactional(readOnly = true) class ChatCharacterBannerService( private val bannerRepository: ChatCharacterBannerRepository, private val characterRepository: ChatCharacterRepository @@ -18,8 +21,18 @@ class ChatCharacterBannerService( /** * 활성화된 모든 배너 조회 (정렬 순서대로) */ - fun getActiveBanners(pageable: Pageable): Page { - return bannerRepository.findByIsActiveTrueOrderBySortOrderAsc(pageable) + fun getActiveBanners(pageable: Pageable, imageHost: String): ChatCharacterBannerListPageResponse { + val banners = bannerRepository.findByIsActiveTrueOrderBySortOrderAsc(pageable) + return ChatCharacterBannerListPageResponse( + totalCount = banners.totalElements, + content = banners.content.map { + ChatCharacterBannerResponse.from( + banner = it, + imageHost = imageHost, + appendLanguageToCharacterName = true + ) + } + ) } fun getDisplayBanners(pageable: Pageable, lang: Lang): Page { diff --git a/src/test/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerServiceIntegrationTest.kt b/src/test/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerServiceIntegrationTest.kt new file mode 100644 index 00000000..34e0bde1 --- /dev/null +++ b/src/test/kotlin/kr/co/vividnext/sodalive/chat/character/service/ChatCharacterBannerServiceIntegrationTest.kt @@ -0,0 +1,76 @@ +package kr.co.vividnext.sodalive.chat.character.service + +import kr.co.vividnext.sodalive.chat.character.ChatCharacter +import kr.co.vividnext.sodalive.chat.character.ChatCharacterBanner +import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterBannerRepository +import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository +import kr.co.vividnext.sodalive.i18n.Lang +import kr.co.vividnext.sodalive.member.Member +import kr.co.vividnext.sodalive.member.MemberRepository +import kr.co.vividnext.sodalive.member.MemberRole +import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Test +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.data.domain.PageRequest +import org.springframework.test.annotation.DirtiesContext +import org.springframework.test.context.ContextConfiguration +import javax.persistence.EntityManager + +@SpringBootTest( + properties = [ + "cloud.aws.cloud-front.host=https://cdn.test", + "spring.datasource.url=jdbc:h2:mem:chat-banner-service-integration;" + + "MODE=MySQL;DATABASE_TO_UPPER=false;NON_KEYWORDS=VALUE;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE" + ] +) +@ContextConfiguration(initializers = [EmbeddedRedisInitializer::class]) +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) +class ChatCharacterBannerServiceIntegrationTest @Autowired constructor( + private val service: ChatCharacterBannerService, + private val characterRepository: ChatCharacterRepository, + private val bannerRepository: ChatCharacterBannerRepository, + private val memberRepository: MemberRepository, + private val entityManager: EntityManager +) { + @Test + @DisplayName("OSIV off 환경에서 관리자 배너 목록 응답 생성 시 lazy 초기화 예외가 발생하지 않는다") + fun shouldCreateAdminBannerListResponseWhenOpenInViewIsDisabled() { + val creator = memberRepository.saveAndFlush( + Member( + email = "character-admin-banner-service@test.com", + password = "password", + nickname = "character-admin-banner-creator", + role = MemberRole.CREATOR + ) + ) + val character = characterRepository.saveAndFlush( + ChatCharacter( + characterUUID = "character-admin-banner-service", + name = "character-admin-banner", + description = "description", + systemPrompt = "system-prompt" + ).apply { + creatorMember = creator + } + ) + bannerRepository.saveAndFlush( + ChatCharacterBanner( + imagePath = "banner/jp.png", + chatCharacter = character, + sortOrder = 1, + lang = Lang.JA + ) + ) + entityManager.clear() + + val response = service.getActiveBanners(PageRequest.of(0, 20), "https://cdn.test") + + assertEquals(1, response.totalCount) + assertEquals(character.id, response.content.first().characterId) + assertEquals("character-admin-banner (일본어)", response.content.first().characterName) + assertEquals("https://cdn.test/banner/jp.png", response.content.first().imagePath) + } +}