feat(recommend): 추천 크리에이터 동시 팔로우 서비스를 추가한다
This commit is contained in:
@@ -0,0 +1,172 @@
|
||||
package kr.co.vividnext.sodalive.v2.recommend.application
|
||||
|
||||
import kr.co.vividnext.sodalive.common.SodaException
|
||||
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.member.following.CreatorFollowing
|
||||
import kr.co.vividnext.sodalive.member.following.CreatorFollowingRepository
|
||||
import kr.co.vividnext.sodalive.support.EmbeddedRedisInitializer
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
import org.junit.jupiter.api.Assertions.assertNotNull
|
||||
import org.junit.jupiter.api.Assertions.assertThrows
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
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.dao.DataIntegrityViolationException
|
||||
import org.springframework.test.context.ContextConfiguration
|
||||
import org.springframework.transaction.annotation.Transactional
|
||||
import javax.persistence.EntityManager
|
||||
|
||||
@SpringBootTest
|
||||
@Transactional
|
||||
@ContextConfiguration(initializers = [EmbeddedRedisInitializer::class])
|
||||
class RecommendedCreatorFollowServiceTest @Autowired constructor(
|
||||
private val service: RecommendedCreatorFollowService,
|
||||
private val memberRepository: MemberRepository,
|
||||
private val creatorFollowingRepository: CreatorFollowingRepository,
|
||||
private val entityManager: EntityManager
|
||||
) {
|
||||
@Test
|
||||
@DisplayName("신규 크리에이터만 팔로우 저장하고 이미 팔로우/본인 id는 서버 내부에서 제외한다")
|
||||
fun shouldFollowOnlyNewCreatorsAndSkipExistingAndSelf() {
|
||||
val member = saveMember("viewer", MemberRole.USER)
|
||||
val newCreator = saveMember("new-creator", MemberRole.CREATOR)
|
||||
val followedCreator = saveMember("followed-creator", MemberRole.CREATOR)
|
||||
saveFollowing(member = member, creator = followedCreator)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
service.followCreators(
|
||||
member = member,
|
||||
creatorIds = listOf(newCreator.id!!, followedCreator.id!!, member.id!!)
|
||||
)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
assertNotNull(creatorFollowingRepository.findByCreatorIdAndMemberId(newCreator.id!!, member.id!!))
|
||||
assertNotNull(creatorFollowingRepository.findByCreatorIdAndMemberId(followedCreator.id!!, member.id!!))
|
||||
assertEquals(2, creatorFollowingRepository.findAll().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("비활성 팔로우 이력이 있으면 신규 row를 만들지 않고 다시 활성화한다")
|
||||
fun shouldReactivateInactiveFollowingWithoutCreatingDuplicateRow() {
|
||||
val member = saveMember("viewer", MemberRole.USER)
|
||||
val creator = saveMember("reactivate-creator", MemberRole.CREATOR)
|
||||
val inactiveFollowing = saveFollowing(member = member, creator = creator).apply {
|
||||
isNotify = false
|
||||
isActive = false
|
||||
}
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
service.followCreators(member = member, creatorIds = listOf(creator.id!!))
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val reactivatedFollowing = creatorFollowingRepository.findByCreatorIdAndMemberId(creator.id!!, member.id!!)
|
||||
assertNotNull(reactivatedFollowing)
|
||||
assertEquals(inactiveFollowing.id, reactivatedFollowing!!.id)
|
||||
assertTrue(reactivatedFollowing.isNotify)
|
||||
assertTrue(reactivatedFollowing.isActive)
|
||||
assertEquals(1, creatorFollowingRepository.findAll().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("이미 활성 팔로우 중이면 알림 설정을 바꾸지 않고 그대로 둔다")
|
||||
fun shouldKeepActiveExistingFollowingNotificationSetting() {
|
||||
val member = saveMember("viewer", MemberRole.USER)
|
||||
val creator = saveMember("active-creator", MemberRole.CREATOR)
|
||||
val existingFollowing = saveFollowing(member = member, creator = creator).apply {
|
||||
isNotify = false
|
||||
isActive = true
|
||||
}
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
service.followCreators(member = member, creatorIds = listOf(creator.id!!))
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val unchangedFollowing = creatorFollowingRepository.findByCreatorIdAndMemberId(creator.id!!, member.id!!)
|
||||
assertNotNull(unchangedFollowing)
|
||||
assertEquals(existingFollowing.id, unchangedFollowing!!.id)
|
||||
assertFalse(unchangedFollowing.isNotify)
|
||||
assertTrue(unchangedFollowing.isActive)
|
||||
assertEquals(1, creatorFollowingRepository.findAll().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("같은 회원과 크리에이터 팔로우 row는 중복 저장할 수 없다")
|
||||
fun shouldRejectDuplicateFollowingRowsForSameMemberAndCreator() {
|
||||
val member = saveMember("viewer", MemberRole.USER)
|
||||
val creator = saveMember("duplicate-creator", MemberRole.CREATOR)
|
||||
saveFollowing(member = member, creator = creator)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val exception = assertThrows(DataIntegrityViolationException::class.java) {
|
||||
saveFollowing(member = member, creator = creator)
|
||||
entityManager.flush()
|
||||
}
|
||||
|
||||
assertNotNull(exception)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("존재하지 않는 id가 하나라도 포함되면 전체 실패하고 신규 저장하지 않는다")
|
||||
fun shouldFailAllAndSaveNothingWhenAnyCreatorIdDoesNotExist() {
|
||||
val member = saveMember("viewer", MemberRole.USER)
|
||||
val validCreator = saveMember("valid-creator", MemberRole.CREATOR)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val exception = assertThrows(SodaException::class.java) {
|
||||
service.followCreators(member = member, creatorIds = listOf(validCreator.id!!, 999_999L))
|
||||
}
|
||||
|
||||
assertEquals("member.validation.creator_not_found", exception.messageKey)
|
||||
assertEquals(0, creatorFollowingRepository.findAll().size)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("크리에이터가 아닌 회원 id가 하나라도 포함되면 전체 실패하고 신규 저장하지 않는다")
|
||||
fun shouldFailAllAndSaveNothingWhenAnyMemberIdIsNotCreator() {
|
||||
val member = saveMember("viewer", MemberRole.USER)
|
||||
val validCreator = saveMember("valid-creator", MemberRole.CREATOR)
|
||||
val nonCreator = saveMember("non-creator", MemberRole.USER)
|
||||
entityManager.flush()
|
||||
entityManager.clear()
|
||||
|
||||
val exception = assertThrows(SodaException::class.java) {
|
||||
service.followCreators(member = member, creatorIds = listOf(validCreator.id!!, nonCreator.id!!))
|
||||
}
|
||||
|
||||
assertEquals("member.validation.creator_not_found", exception.messageKey)
|
||||
assertEquals(0, creatorFollowingRepository.findAll().size)
|
||||
}
|
||||
|
||||
private fun saveMember(seed: String, role: MemberRole): Member {
|
||||
return memberRepository.saveAndFlush(
|
||||
Member(
|
||||
email = "$seed@test.com",
|
||||
password = "password",
|
||||
nickname = seed,
|
||||
role = role
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun saveFollowing(member: Member, creator: Member): CreatorFollowing {
|
||||
return creatorFollowingRepository.saveAndFlush(
|
||||
CreatorFollowing().apply {
|
||||
this.member = member
|
||||
this.creator = creator
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user