fix(user-creator-chat): Redis 전달 예외 fallback 범위를 좁힌다
This commit is contained in:
@@ -18,6 +18,7 @@ import kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatPres
|
||||
import kr.co.vividnext.sodalive.v2.usercreatorchat.websocket.UserCreatorChatRoomMessageBroker
|
||||
import org.junit.jupiter.api.Assertions.assertEquals
|
||||
import org.junit.jupiter.api.Assertions.assertFalse
|
||||
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
|
||||
@@ -25,6 +26,7 @@ import org.junit.jupiter.api.Test
|
||||
import org.mockito.ArgumentCaptor
|
||||
import org.mockito.Mockito
|
||||
import org.springframework.context.ApplicationEventPublisher
|
||||
import org.springframework.dao.DataAccessResourceFailureException
|
||||
import org.springframework.data.domain.PageRequest
|
||||
import org.springframework.mock.web.MockMultipartFile
|
||||
import java.io.ByteArrayInputStream
|
||||
@@ -204,6 +206,33 @@ class UserCreatorChatServiceTest {
|
||||
Mockito.verifyNoInteractions(roomMessageBroker)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("WebSocket 텍스트 전송은 Redis presence 확인 실패 시 메시지를 저장하고 푸시 이벤트를 발행한다")
|
||||
fun shouldPublishPushEventWhenPresenceCheckFailsDuringWebSocketTextMessage() {
|
||||
val user = member(1L, "user")
|
||||
val creator = member(2L, "creator")
|
||||
val room = room(10L)
|
||||
val senderParticipant = participant(100L, room, user)
|
||||
val recipientParticipant = participant(101L, room, creator)
|
||||
Mockito.`when`(roomRepository.findByIdAndIsActiveTrue(10L)).thenReturn(room)
|
||||
Mockito.`when`(participantRepository.findActiveByRoomIdAndMemberId(10L, 1L)).thenReturn(senderParticipant)
|
||||
Mockito.`when`(participantRepository.findActiveOpponent(10L, 1L)).thenReturn(recipientParticipant)
|
||||
Mockito.`when`(presenceService.hasPresence(10L, 2L))
|
||||
.thenThrow(DataAccessResourceFailureException("redis down"))
|
||||
Mockito.`when`(messageRepository.save(Mockito.any(UserCreatorChatMessage::class.java))).thenAnswer { invocation ->
|
||||
(invocation.arguments[0] as UserCreatorChatMessage).apply { id = 207L }
|
||||
}
|
||||
|
||||
val response = service.sendTextMessageByWebSocket(memberId = 1L, roomId = 10L, textMessage = "hello")
|
||||
|
||||
assertEquals(207L, response.messageId)
|
||||
val eventCaptor = ArgumentCaptor.forClass(FcmEvent::class.java)
|
||||
Mockito.verify(eventPublisher).publishEvent(eventCaptor.capture())
|
||||
assertEquals(FcmEventType.INDIVIDUAL, eventCaptor.value.type)
|
||||
assertEquals(listOf(2L), eventCaptor.value.recipients)
|
||||
Mockito.verifyNoInteractions(roomMessageBroker)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("음성 메시지 REST 전송은 상대방 presence가 있으면 WebSocket broker로 MESSAGE를 발행하고 푸시를 보내지 않는다")
|
||||
fun shouldPublishVoiceMessageToWebSocketWhenOpponentPresenceExists() {
|
||||
@@ -266,6 +295,63 @@ class UserCreatorChatServiceTest {
|
||||
Mockito.verifyNoInteractions(roomMessageBroker)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("음성 메시지 REST 전송은 Redis broker 발행 실패 시 푸시 이벤트를 발행한다")
|
||||
fun shouldPublishPushEventWhenBrokerPublishFailsDuringVoiceMessage() {
|
||||
val user = member(1L, "user")
|
||||
val creator = member(2L, "creator")
|
||||
val room = room(10L)
|
||||
val senderParticipant = participant(100L, room, user)
|
||||
val recipientParticipant = participant(101L, room, creator)
|
||||
Mockito.`when`(roomRepository.findByIdAndIsActiveTrue(10L)).thenReturn(room)
|
||||
Mockito.`when`(participantRepository.findActiveByRoomIdAndMemberId(10L, 1L)).thenReturn(senderParticipant)
|
||||
Mockito.`when`(participantRepository.findActiveOpponent(10L, 1L)).thenReturn(recipientParticipant)
|
||||
Mockito.`when`(presenceService.hasPresence(10L, 2L)).thenReturn(true)
|
||||
Mockito.doThrow(DataAccessResourceFailureException("redis publish down"))
|
||||
.`when`(roomMessageBroker)
|
||||
.publish(Mockito.eq(10L), Mockito.eq(2L), Mockito.anyString())
|
||||
Mockito.`when`(messageRepository.save(Mockito.any(UserCreatorChatMessage::class.java))).thenAnswer { invocation ->
|
||||
(invocation.arguments[0] as UserCreatorChatMessage).apply { id = 208L }
|
||||
}
|
||||
givenVoiceUploadReturns("voice/208.m4a")
|
||||
|
||||
val response = service.sendVoiceMessage(user, 10L, voiceFile(), "{}")
|
||||
|
||||
assertEquals(208L, response.message.messageId)
|
||||
assertFalse(response.deliveredRealtime)
|
||||
assertTrue(response.pushSent)
|
||||
val eventCaptor = ArgumentCaptor.forClass(FcmEvent::class.java)
|
||||
Mockito.verify(eventPublisher).publishEvent(eventCaptor.capture())
|
||||
assertEquals(FcmEventType.INDIVIDUAL, eventCaptor.value.type)
|
||||
assertEquals(listOf(2L), eventCaptor.value.recipients)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("음성 메시지 REST 전송은 Redis 계층이 아닌 broker 예외를 푸시로 숨기지 않는다")
|
||||
fun shouldPropagateNonRedisBrokerExceptionDuringVoiceMessage() {
|
||||
val user = member(1L, "user")
|
||||
val creator = member(2L, "creator")
|
||||
val room = room(10L)
|
||||
val senderParticipant = participant(100L, room, user)
|
||||
val recipientParticipant = participant(101L, room, creator)
|
||||
Mockito.`when`(roomRepository.findByIdAndIsActiveTrue(10L)).thenReturn(room)
|
||||
Mockito.`when`(participantRepository.findActiveByRoomIdAndMemberId(10L, 1L)).thenReturn(senderParticipant)
|
||||
Mockito.`when`(participantRepository.findActiveOpponent(10L, 1L)).thenReturn(recipientParticipant)
|
||||
Mockito.`when`(presenceService.hasPresence(10L, 2L)).thenReturn(true)
|
||||
Mockito.doThrow(IllegalStateException("programming error"))
|
||||
.`when`(roomMessageBroker)
|
||||
.publish(Mockito.eq(10L), Mockito.eq(2L), Mockito.anyString())
|
||||
Mockito.`when`(messageRepository.save(Mockito.any(UserCreatorChatMessage::class.java))).thenAnswer { invocation ->
|
||||
(invocation.arguments[0] as UserCreatorChatMessage).apply { id = 209L }
|
||||
}
|
||||
givenVoiceUploadReturns("voice/209.m4a")
|
||||
|
||||
assertThrows(IllegalStateException::class.java) {
|
||||
service.sendVoiceMessage(user, 10L, voiceFile(), "{}")
|
||||
}
|
||||
Mockito.verifyNoInteractions(eventPublisher)
|
||||
}
|
||||
|
||||
@Test
|
||||
@DisplayName("커서가 있으면 기본 20개 기준으로 이전 메시지를 조회한다")
|
||||
fun shouldGetPreviousMessagesWithDefaultLimitWhenCursorExists() {
|
||||
|
||||
Reference in New Issue
Block a user