test(aicharacter): 크리에이터 회원 연결 검증을 보강한다
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
package kr.co.vividnext.sodalive.chat.character.service
|
||||
|
||||
import kr.co.vividnext.sodalive.chat.character.ChatCharacter
|
||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberKind
|
||||
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.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.springframework.beans.factory.annotation.Autowired
|
||||
import org.springframework.boot.test.context.SpringBootTest
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import javax.persistence.EntityManager
|
||||
|
||||
@SpringBootTest
|
||||
@Transactional
|
||||
@ContextConfiguration(initializers = [EmbeddedRedisInitializer::class])
|
||||
class ChatCharacterCreatorMemberServiceIntegrationTest @Autowired constructor(
|
||||
private val creatorMemberService: ChatCharacterCreatorMemberService,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val chatCharacterRepository: ChatCharacterRepository,
|
||||
private val entityManager: EntityManager
|
||||
) {
|
||||
@Test
|
||||
fun `ChatCharacter creatorMember 관계와 repository 메서드를 사용할 수 있다`() {
|
||||
val member = memberRepository.save(createMember(memberKind = MemberKind.AI_CHARACTER))
|
||||
val chatCharacter = chatCharacterRepository.save(createCharacter().apply { creatorMember = member })
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val found = chatCharacterRepository.findByCreatorMemberId(member.id!!)
|
||||
|
||||
assertNotNull(found)
|
||||
assertEquals(chatCharacter.id, found!!.id)
|
||||
assertEquals(true, chatCharacterRepository.existsByCreatorMemberId(member.id!!))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AI 캐릭터용 Member를 생성하고 표시 정보를 복사한다`() {
|
||||
val chatCharacter = createCharacter(
|
||||
name = "소다",
|
||||
description = "AI 캐릭터 설명",
|
||||
imagePath = "characters/1/profile.png"
|
||||
)
|
||||
|
||||
val member = creatorMemberService.ensureAiCharacterCreatorMember(chatCharacter)
|
||||
chatCharacterRepository.save(chatCharacter)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val savedMember = memberRepository.findById(member.id!!).orElseThrow()
|
||||
val savedCharacter = chatCharacterRepository.findByCreatorMemberId(member.id!!)
|
||||
assertNotNull(savedCharacter)
|
||||
assertNull(savedMember.email)
|
||||
assertEquals("", savedMember.password)
|
||||
assertEquals(MemberRole.CREATOR, savedMember.role)
|
||||
assertEquals(MemberKind.AI_CHARACTER, savedMember.memberKind)
|
||||
assertEquals("소다", savedMember.nickname)
|
||||
assertEquals("characters/1/profile.png", savedMember.profileImage)
|
||||
assertEquals("AI 캐릭터 설명", savedMember.introduce)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AI 캐릭터용 Member 표시 정보를 동기화한다`() {
|
||||
val member = memberRepository.save(
|
||||
createMember(memberKind = MemberKind.AI_CHARACTER).apply {
|
||||
nickname = "old-name"
|
||||
profileImage = "old/profile.png"
|
||||
introduce = "old-description"
|
||||
}
|
||||
)
|
||||
val chatCharacter = chatCharacterRepository.save(
|
||||
createCharacter(
|
||||
name = "new-name",
|
||||
description = "new-description",
|
||||
imagePath = "new/profile.png"
|
||||
).apply { creatorMember = member }
|
||||
)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val savedCharacter = chatCharacterRepository.findById(chatCharacter.id!!).orElseThrow()
|
||||
creatorMemberService.syncAiCharacterCreatorMemberDisplayFields(savedCharacter)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val savedMember = memberRepository.findById(member.id!!).orElseThrow()
|
||||
assertEquals("new-name", savedMember.nickname)
|
||||
assertEquals("new/profile.png", savedMember.profileImage)
|
||||
assertEquals("new-description", savedMember.introduce)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `동기화 대상 creatorMember가 없으면 저장 실패를 위해 예외를 던진다`() {
|
||||
val chatCharacter = createCharacter(
|
||||
id = 1L,
|
||||
name = "missing-creator-member",
|
||||
description = "description"
|
||||
)
|
||||
|
||||
val exception = assertThrows(SodaException::class.java) {
|
||||
creatorMemberService.syncAiCharacterCreatorMemberDisplayFields(chatCharacter)
|
||||
}
|
||||
|
||||
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `사람 크리에이터 Member 표시 정보는 덮어쓰지 않는다`() {
|
||||
val member = memberRepository.save(
|
||||
createMember(memberKind = MemberKind.HUMAN).apply {
|
||||
nickname = "human-name"
|
||||
profileImage = "human/profile.png"
|
||||
introduce = "human-description"
|
||||
}
|
||||
)
|
||||
val chatCharacter = chatCharacterRepository.save(
|
||||
createCharacter(
|
||||
name = "ai-name",
|
||||
description = "ai-description",
|
||||
imagePath = "ai/profile.png"
|
||||
).apply { creatorMember = member }
|
||||
)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val savedCharacter = chatCharacterRepository.findById(chatCharacter.id!!).orElseThrow()
|
||||
creatorMemberService.syncAiCharacterCreatorMemberDisplayFields(savedCharacter)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val savedMember = memberRepository.findById(member.id!!).orElseThrow()
|
||||
assertEquals("human-name", savedMember.nickname)
|
||||
assertEquals("human/profile.png", savedMember.profileImage)
|
||||
assertEquals("human-description", savedMember.introduce)
|
||||
}
|
||||
|
||||
private fun createCharacter(
|
||||
id: Long? = null,
|
||||
name: String = "character-name",
|
||||
description: String = "character-description",
|
||||
imagePath: String? = null
|
||||
): ChatCharacter {
|
||||
val character = ChatCharacter(
|
||||
characterUUID = "character-uuid-$name",
|
||||
name = name,
|
||||
description = description,
|
||||
systemPrompt = "system-prompt"
|
||||
)
|
||||
character.id = id
|
||||
character.imagePath = imagePath
|
||||
return character
|
||||
}
|
||||
|
||||
private fun createMember(memberKind: MemberKind): Member {
|
||||
return Member(
|
||||
email = if (memberKind == MemberKind.HUMAN) "human-${System.nanoTime()}@example.com" else null,
|
||||
password = if (memberKind == MemberKind.HUMAN) "password" else "",
|
||||
nickname = "member-name",
|
||||
role = MemberRole.CREATOR,
|
||||
memberKind = memberKind
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -7,125 +7,23 @@ import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterHobbyRepo
|
||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterRepository
|
||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterTagRepository
|
||||
import kr.co.vividnext.sodalive.chat.character.repository.ChatCharacterValueRepository
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
import kr.co.vividnext.sodalive.member.Member
|
||||
import kr.co.vividnext.sodalive.member.MemberKind
|
||||
import kr.co.vividnext.sodalive.member.MemberRepository
|
||||
import kr.co.vividnext.sodalive.member.MemberRole
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertNull
|
||||
import org.junit.jupiter.api.Assertions.assertSame
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.mockito.Mockito
|
||||
import java.util.Optional
|
||||
|
||||
class ChatCharacterCreatorMemberServiceTest {
|
||||
private lateinit var memberRepository: MemberRepository
|
||||
private lateinit var chatCharacterRepository: ChatCharacterRepository
|
||||
private lateinit var creatorMemberService: ChatCharacterCreatorMemberService
|
||||
|
||||
@BeforeEach
|
||||
fun setUp() {
|
||||
memberRepository = Mockito.mock(MemberRepository::class.java)
|
||||
chatCharacterRepository = Mockito.mock(ChatCharacterRepository::class.java)
|
||||
creatorMemberService = ChatCharacterCreatorMemberService(memberRepository)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ChatCharacter creatorMember 관계와 repository 메서드를 사용할 수 있다`() {
|
||||
val member = createMember(memberKind = MemberKind.AI_CHARACTER)
|
||||
val chatCharacter = createCharacter().apply { creatorMember = member }
|
||||
|
||||
Mockito.`when`(chatCharacterRepository.findByCreatorMemberId(1L)).thenReturn(chatCharacter)
|
||||
Mockito.`when`(chatCharacterRepository.existsByCreatorMemberId(1L)).thenReturn(true)
|
||||
|
||||
assertSame(member, chatCharacter.creatorMember)
|
||||
assertSame(chatCharacter, chatCharacterRepository.findByCreatorMemberId(1L))
|
||||
assertEquals(true, chatCharacterRepository.existsByCreatorMemberId(1L))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AI 캐릭터용 Member를 생성하고 표시 정보를 복사한다`() {
|
||||
val chatCharacter = createCharacter(
|
||||
name = "소다",
|
||||
description = "AI 캐릭터 설명",
|
||||
imagePath = "characters/1/profile.png"
|
||||
)
|
||||
Mockito.`when`(memberRepository.save(Mockito.any(Member::class.java))).thenAnswer { invocation ->
|
||||
(invocation.arguments[0] as Member).apply { id = 10L }
|
||||
}
|
||||
|
||||
val member = creatorMemberService.ensureAiCharacterCreatorMember(chatCharacter)
|
||||
|
||||
assertSame(member, chatCharacter.creatorMember)
|
||||
assertNull(member.email)
|
||||
assertEquals("", member.password)
|
||||
assertEquals(MemberRole.CREATOR, member.role)
|
||||
assertEquals(MemberKind.AI_CHARACTER, member.memberKind)
|
||||
assertEquals("소다", member.nickname)
|
||||
assertEquals("characters/1/profile.png", member.profileImage)
|
||||
assertEquals("AI 캐릭터 설명", member.introduce)
|
||||
Mockito.verify(memberRepository).save(member)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `AI 캐릭터용 Member 표시 정보를 동기화한다`() {
|
||||
val member = createMember(memberKind = MemberKind.AI_CHARACTER).apply {
|
||||
nickname = "old-name"
|
||||
profileImage = "old/profile.png"
|
||||
introduce = "old-description"
|
||||
}
|
||||
val chatCharacter = createCharacter(
|
||||
name = "new-name",
|
||||
description = "new-description",
|
||||
imagePath = "new/profile.png"
|
||||
).apply { creatorMember = member }
|
||||
|
||||
creatorMemberService.syncAiCharacterCreatorMemberDisplayFields(chatCharacter)
|
||||
|
||||
assertEquals("new-name", member.nickname)
|
||||
assertEquals("new/profile.png", member.profileImage)
|
||||
assertEquals("new-description", member.introduce)
|
||||
Mockito.verify(memberRepository).save(member)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `동기화 대상 creatorMember가 없으면 저장 실패를 위해 예외를 던진다`() {
|
||||
val chatCharacter = createCharacter(
|
||||
id = 1L,
|
||||
name = "missing-creator-member",
|
||||
description = "description"
|
||||
)
|
||||
|
||||
val exception = assertThrows(SodaException::class.java) {
|
||||
creatorMemberService.syncAiCharacterCreatorMemberDisplayFields(chatCharacter)
|
||||
}
|
||||
|
||||
assertEquals("common.error.invalid_request", exception.messageKey)
|
||||
Mockito.verifyNoInteractions(memberRepository)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `사람 크리에이터 Member 표시 정보는 덮어쓰지 않는다`() {
|
||||
val member = createMember(memberKind = MemberKind.HUMAN).apply {
|
||||
nickname = "human-name"
|
||||
profileImage = "human/profile.png"
|
||||
introduce = "human-description"
|
||||
}
|
||||
val chatCharacter = createCharacter(
|
||||
name = "ai-name",
|
||||
description = "ai-description",
|
||||
imagePath = "ai/profile.png"
|
||||
).apply { creatorMember = member }
|
||||
|
||||
creatorMemberService.syncAiCharacterCreatorMemberDisplayFields(chatCharacter)
|
||||
|
||||
assertEquals("human-name", member.nickname)
|
||||
assertEquals("human/profile.png", member.profileImage)
|
||||
assertEquals("human-description", member.introduce)
|
||||
Mockito.verifyNoInteractions(memberRepository)
|
||||
creatorMemberService = Mockito.mock(ChatCharacterCreatorMemberService::class.java)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -172,7 +70,6 @@ class ChatCharacterCreatorMemberServiceTest {
|
||||
}
|
||||
|
||||
private fun createChatCharacterService(): ChatCharacterService {
|
||||
creatorMemberService = Mockito.mock(ChatCharacterCreatorMemberService::class.java)
|
||||
return ChatCharacterService(
|
||||
chatCharacterRepository = chatCharacterRepository,
|
||||
tagRepository = Mockito.mock(ChatCharacterTagRepository::class.java),
|
||||
|
||||
Reference in New Issue
Block a user