diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java index 8e153623a..196903d31 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketChatSessions.java @@ -10,15 +10,11 @@ import static com.ddang.ddang.chat.domain.WebSocketSessions.CHAT_ROOM_ID_KEY; -@Component @Getter +@Component public class WebSocketChatSessions { - private final Map chatRoomSessions; - - public WebSocketChatSessions() { - this.chatRoomSessions = new ConcurrentHashMap<>(); - } + private final Map chatRoomSessions = new ConcurrentHashMap<>(); public void add(final WebSocketSession session, final Long chatRoomId) { chatRoomSessions.putIfAbsent(chatRoomId, new WebSocketSessions()); diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java index 562040826..7619377a5 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/domain/WebSocketSessions.java @@ -11,26 +11,23 @@ public class WebSocketSessions { protected static final String CHAT_ROOM_ID_KEY = "chatRoomId"; + private static final String USER_ID_KEY = "userId"; - private final Set sessions; - - public WebSocketSessions() { - this.sessions = Collections.newSetFromMap(new ConcurrentHashMap<>()); - } + private final Set sessions = Collections.newSetFromMap(new ConcurrentHashMap<>()); public void putIfAbsent(final WebSocketSession session, final Long chatRoomId) { if (!sessions.contains(session)) { - sessions.add(session); session.getAttributes().put(CHAT_ROOM_ID_KEY, chatRoomId); + sessions.add(session); } } - public void remove(final WebSocketSession session) { - sessions.remove(session); - } - public boolean contains(final Long userId) { return sessions.stream() - .anyMatch(session -> session.getAttributes().get("userId") == userId); + .anyMatch(session -> session.getAttributes().get(USER_ID_KEY) == userId); + } + + public void remove(final WebSocketSession session) { + sessions.remove(session); } } diff --git a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java index ab62416d9..03470a522 100644 --- a/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java +++ b/backend/ddang/src/main/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProvider.java @@ -43,7 +43,7 @@ public TextMessageType supportTextMessageType() { public List handleCreateSendMessage( final WebSocketSession session, final Map data - ) throws Exception { + ) throws JsonProcessingException { final SessionAttributeDto sessionAttribute = getSessionAttributes(session); final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class); sessions.add(session, messageData.chatRoomId()); diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/WebSocketSessionsTest.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/WebSocketSessionsTest.java new file mode 100644 index 000000000..15fe5846a --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/WebSocketSessionsTest.java @@ -0,0 +1,99 @@ +package com.ddang.ddang.chat.domain; + +import com.ddang.ddang.chat.domain.fixture.WebSocketSessionsTestFixture; +import org.assertj.core.api.SoftAssertions; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.springframework.web.socket.WebSocketSession; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class WebSocketSessionsTest extends WebSocketSessionsTestFixture { + + WebSocketSessions sessions; + + WebSocketSession session; + + @BeforeEach + void setUp() { + sessions = new WebSocketSessions(); + session = mock(WebSocketSession.class); + } + + @Test + void 저장되지_않은_세션이라면_추가한다() { + // given + given(session.getAttributes()).willReturn(세션_attribute_정보); + + // when + sessions.putIfAbsent(session, 채팅방_아이디); + + // then + final boolean actual = sessions.getSessions().contains(session); + SoftAssertions.assertSoftly(softAssertions -> { + softAssertions.assertThat(sessions.getSessions()).hasSize(1); + softAssertions.assertThat(actual).isTrue(); + }); + } + + @Test + void 이미_저장된_세션이라면_추가하지_않는다() { + // given + given(session.getAttributes()).willReturn(세션_attribute_정보); + sessions.getSessions().add(session); + + // when + sessions.putIfAbsent(session, 채팅방_아이디); + + // then + final boolean actual = sessions.getSessions().contains(session); + SoftAssertions.assertSoftly(softAssertions -> { + softAssertions.assertThat(sessions.getSessions()).hasSize(1); + softAssertions.assertThat(actual).isTrue(); + }); + } + + @Test + void 이미_저장된_세선이라면_참을_반환한다() { + // given + given(session.getAttributes()).willReturn(세션_attribute_정보); + sessions.getSessions().add(session); + + // when + final boolean actual = sessions.contains(사용자_아이디); + + // then + assertThat(actual).isTrue(); + } + + @Test + void 저장되지_않은_세선이라면_거짓을_반환한다() { + // given + given(session.getAttributes()).willReturn(세션_attribute_정보); + + // when + final boolean actual = sessions.contains(사용자_아이디); + + // then + assertThat(actual).isFalse(); + } + + @Test + void 세션을_제거한다() { + // given + given(session.getAttributes()).willReturn(세션_attribute_정보); + + // when + sessions.remove(session); + + // then + final boolean actual = sessions.getSessions().contains(session); + assertThat(actual).isFalse(); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/fixture/WebSocketSessionsTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/fixture/WebSocketSessionsTestFixture.java new file mode 100644 index 000000000..1e96befe9 --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/domain/fixture/WebSocketSessionsTestFixture.java @@ -0,0 +1,12 @@ +package com.ddang.ddang.chat.domain.fixture; + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("NonAsciiCharacters") +public class WebSocketSessionsTestFixture { + + protected Long 사용자_아이디 = 1L; + protected Map 세션_attribute_정보 = new HashMap<>(Map.of("userId", 사용자_아이디, "baseUrl", "/images")); + protected Long 채팅방_아이디 = 1L; +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java new file mode 100644 index 000000000..06d38bb20 --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/ChatWebSocketHandleTextMessageProviderTest.java @@ -0,0 +1,143 @@ +package com.ddang.ddang.chat.handler; + +import com.ddang.ddang.chat.application.event.MessageNotificationEvent; +import com.ddang.ddang.chat.domain.WebSocketChatSessions; +import com.ddang.ddang.chat.handler.fixture.ChatWebSocketHandleTextMessageProviderTestFixture; +import com.ddang.ddang.configuration.IsolateDatabase; +import com.ddang.ddang.notification.application.NotificationService; +import com.ddang.ddang.notification.application.dto.CreateNotificationDto; +import com.ddang.ddang.notification.domain.NotificationStatus; +import com.ddang.ddang.websocket.handler.dto.SendMessageDto; +import com.ddang.ddang.websocket.handler.dto.TextMessageType; +import com.fasterxml.jackson.core.JsonProcessingException; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.boot.test.mock.mockito.SpyBean; +import org.springframework.test.context.event.ApplicationEvents; +import org.springframework.test.context.event.RecordApplicationEvents; +import org.springframework.web.socket.WebSocketSession; + +import java.util.List; +import java.util.Set; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.willDoNothing; +import static org.mockito.BDDMockito.willReturn; + +@IsolateDatabase +@RecordApplicationEvents +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class ChatWebSocketHandleTextMessageProviderTest extends ChatWebSocketHandleTextMessageProviderTestFixture { + + @Autowired + ChatWebSocketHandleTextMessageProvider provider; + + @SpyBean + WebSocketChatSessions sessions; + + @Mock + WebSocketSession writerSession; + + @Mock + WebSocketSession receiverSession; + + @MockBean + NotificationService notificationService; + + @Autowired + ApplicationEvents events; + + @Test + void 지원하는_웹소켓_핸들링_타입을_반환한다() { + // when + final TextMessageType actual = provider.supportTextMessageType(); + + // then + assertThat(actual).isEqualTo(TextMessageType.CHATTINGS); + } + + @Test + void 메시지_생성시_수신자가_웹소켓_통신_중이라면_발신자_수신자_모두에게_메시지를_보낸다() throws JsonProcessingException { + // given + given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); + given(receiverSession.getAttributes()).willReturn(수신자_세션_attribute_정보); + willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); + willReturn(true).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); + willReturn(Set.of(writerSession, receiverSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + + // when + final List actual = provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); + + // then + assertThat(actual).hasSize(2); + } + + @Test + void 메시지_생성시_수신자가_웹소켓_통신_중이지_않다면_발신자에게만_메시지를_전달한다() throws JsonProcessingException { + // given + given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); + willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); + willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); + willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + + // when + final List actual = provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); + + // then + assertThat(actual).hasSize(1); + } + + @Test + void 메시지_생성시_수신자가_웹소켓_통신_중이지_않다면_수신자에게_알림을_보낸다() throws Exception { + // given + given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); + willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); + willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); + willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + given(notificationService.send(any(CreateNotificationDto.class))).willReturn(NotificationStatus.SUCCESS); + + // when + provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); + final long actual = events.stream(MessageNotificationEvent.class).count(); + + // then + assertThat(actual).isEqualTo(1); + } + + @Test + void 메시지_생성시_수신자에게_알림을_보낸기에_실패하더라도_정상적으로_메시지가_전달된다() throws Exception { + // given + given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); + willDoNothing().given(sessions).add(writerSession, 채팅방.getId()); + willReturn(false).given(sessions).containsByUserId(채팅방.getId(), 수신자.getId()); + willReturn(Set.of(writerSession)).given(sessions).getSessionsByChatRoomId(채팅방.getId()); + given(notificationService.send(any(CreateNotificationDto.class))).willReturn(NotificationStatus.FAIL); + + // when + final List actual = provider.handleCreateSendMessage(writerSession, 메시지_전송_데이터); + + // then + assertThat(actual).hasSize(1); + } + + @Test + void 세션을_삭제한다() { + // given + given(writerSession.getAttributes()).willReturn(발신자_세션_attribute_정보); + sessions.add(writerSession, 채팅방.getId()); + + // when + provider.remove(writerSession); + + // then + final boolean actual = sessions.containsByUserId(채팅방.getId(), 발신자.getId()); + assertThat(actual).isFalse(); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java new file mode 100644 index 000000000..99524f23a --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/chat/handler/fixture/ChatWebSocketHandleTextMessageProviderTestFixture.java @@ -0,0 +1,88 @@ +package com.ddang.ddang.chat.handler.fixture; + +import com.ddang.ddang.auction.domain.Auction; +import com.ddang.ddang.auction.domain.BidUnit; +import com.ddang.ddang.auction.domain.Price; +import com.ddang.ddang.auction.domain.repository.AuctionRepository; +import com.ddang.ddang.category.domain.Category; +import com.ddang.ddang.category.infrastructure.persistence.JpaCategoryRepository; +import com.ddang.ddang.chat.domain.ChatRoom; +import com.ddang.ddang.chat.domain.repository.ChatRoomRepository; +import com.ddang.ddang.image.domain.ProfileImage; +import com.ddang.ddang.user.domain.Reliability; +import com.ddang.ddang.user.domain.User; +import com.ddang.ddang.user.domain.repository.UserRepository; +import org.junit.jupiter.api.BeforeEach; +import org.springframework.beans.factory.annotation.Autowired; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("NonAsciiCharacters") +public class ChatWebSocketHandleTextMessageProviderTestFixture { + + @Autowired + private JpaCategoryRepository categoryRepository; + + @Autowired + private AuctionRepository auctionRepository; + + @Autowired + private UserRepository userRepository; + + @Autowired + private ChatRoomRepository chatRoomRepository; + + protected ChatRoom 채팅방; + protected User 발신자; + protected User 수신자; + + protected Map 발신자_세션_attribute_정보; + protected Map 수신자_세션_attribute_정보; + protected Map 메시지_전송_데이터; + + @BeforeEach + void setUpFixture() { + final Category 전자기기 = new Category("전자기기"); + final Category 전자기기_하위_노트북 = new Category("노트북"); + 전자기기.addSubCategory(전자기기_하위_노트북); + categoryRepository.save(전자기기); + + final Auction 경매 = Auction.builder() + .title("경매") + .description("description") + .bidUnit(new BidUnit(1_000)) + .startPrice(new Price(10_000)) + .closingTime(LocalDateTime.now().plusDays(3L)) + .build(); + auctionRepository.save(경매); + + 발신자 = User.builder() + .name("발신자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12345") + .build(); + 수신자 = User.builder() + .name("수신자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12346") + .build(); + userRepository.save(발신자); + userRepository.save(수신자); + + 채팅방 = new ChatRoom(경매, 발신자); + + chatRoomRepository.save(채팅방); + + 발신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 발신자.getId(), "baseUrl", "/images")); + 수신자_세션_attribute_정보 = new HashMap<>(Map.of("userId", 수신자.getId(), "baseUrl", "/images")); + 메시지_전송_데이터 = Map.of( + "chatRoomId", String.valueOf(채팅방.getId()), + "receiverId", String.valueOf(수신자.getId()), + "contents", "메시지 내용" + ); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/notification/application/NotificationEventListenerTest.java b/backend/ddang/src/test/java/com/ddang/ddang/notification/application/NotificationEventListenerTest.java index 2bdc79d53..9b50f3ea2 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/notification/application/NotificationEventListenerTest.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/notification/application/NotificationEventListenerTest.java @@ -24,7 +24,6 @@ import org.springframework.web.socket.WebSocketSession; import java.util.List; -import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; @@ -79,7 +78,7 @@ class NotificationEventListenerTest extends NotificationEventListenerFixture { @Test void 메시지를_전송하면_알림을_전송한다() throws Exception { // given - given(session.getAttributes()).willReturn(Map.of(사용자_아이디_키, 발신자_겸_판매자.getId(), 이미지_경로_키, 이미지_절대_경로)); + given(session.getAttributes()).willReturn(세션_attribute_정보); // when chatWebSocketHandleTextMessageProvider.handleCreateSendMessage(session, 메시지_전송_데이터); @@ -92,7 +91,7 @@ class NotificationEventListenerTest extends NotificationEventListenerFixture { @Test void 메시지_알림_전송이_실패해도_메시지는_저장된다() throws Exception { // given - given(session.getAttributes()).willReturn(Map.of(사용자_아이디_키, 발신자_겸_판매자.getId(), 이미지_경로_키, 이미지_절대_경로)); + given(session.getAttributes()).willReturn(세션_attribute_정보); given(firebaseMessaging.send(any())).willThrow(FirebaseMessagingException.class); // when diff --git a/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java index fd9cffd2c..847fbcb40 100644 --- a/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java +++ b/backend/ddang/src/test/java/com/ddang/ddang/notification/application/fixture/NotificationEventListenerFixture.java @@ -30,6 +30,7 @@ import org.springframework.beans.factory.annotation.Autowired; import java.time.LocalDateTime; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -60,20 +61,18 @@ public class NotificationEventListenerFixture { protected QuestionNotificationEvent 질문_알림_이벤트; protected AnswerNotificationEvent 답변_알림_이벤트; - protected User 발신자_겸_판매자; - protected String 사용자_아이디_키 = "userId"; - protected String 이미지_경로_키 = "baseUrl"; + protected Map 세션_attribute_정보; protected Map 메시지_전송_데이터; protected String 이미지_절대_경로 = "/imageUrl"; @BeforeEach void setUpFixture() { - 발신자_겸_판매자 = User.builder() - .name("발신자 겸 판매자") - .profileImage(new ProfileImage("upload.png", "store.png")) - .reliability(new Reliability(4.7d)) - .oauthId("12345") - .build(); + final User 발신자_겸_판매자 = User.builder() + .name("발신자 겸 판매자") + .profileImage(new ProfileImage("upload.png", "store.png")) + .reliability(new Reliability(4.7d)) + .oauthId("12345") + .build(); final User 수신자_겸_기존_입찰자 = User.builder() .name("수신자 겸 기존 입찰자") .profileImage(new ProfileImage("upload.png", "store.png")) @@ -117,13 +116,14 @@ void setUpFixture() { chatRoomRepository.save(채팅방); bidRepository.save(bid); + 세션_attribute_정보 = new HashMap<>(Map.of( + "userId", 발신자_겸_판매자.getId(), + "baseUrl", 이미지_절대_경로 + )); 메시지_전송_데이터 = Map.of( - "chatRoomId", - String.valueOf(채팅방.getId()), - "receiverId", - String.valueOf(수신자_겸_기존_입찰자.getId()), - "contents", - "메시지 내용" + "chatRoomId", String.valueOf(채팅방.getId()), + "receiverId", String.valueOf(수신자_겸_기존_입찰자.getId()), + "contents", "메시지 내용" ); 입찰_생성_DTO = new CreateBidDto(경매.getId(), 1000, 새로운_입찰자.getId()); diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java new file mode 100644 index 000000000..40b7cca3e --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/WebSocketHandlerTest.java @@ -0,0 +1,72 @@ +package com.ddang.ddang.websocket.handler; + +import com.ddang.ddang.chat.handler.ChatWebSocketHandleTextMessageProvider; +import com.ddang.ddang.configuration.IsolateDatabase; +import com.ddang.ddang.websocket.handler.dto.SendMessageDto; +import com.ddang.ddang.websocket.handler.dto.TextMessageType; +import com.ddang.ddang.websocket.handler.fixture.WebSocketHandlerTestFixture; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.junit.jupiter.api.DisplayNameGeneration; +import org.junit.jupiter.api.DisplayNameGenerator; +import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.WebSocketSession; + +import java.util.List; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyMap; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +@IsolateDatabase +@DisplayNameGeneration(DisplayNameGenerator.ReplaceUnderscores.class) +@SuppressWarnings("NonAsciiCharacters") +class WebSocketHandlerTest extends WebSocketHandlerTestFixture { + + @MockBean + ChatWebSocketHandleTextMessageProvider provider; + + @MockBean + WebSocketHandleTextMessageProviderComposite providerComposite; + + @Autowired + WebSocketHandler webSocketHandler; + + @Mock + WebSocketSession session; + + @Test + void 세션의_타입_속성이_채팅이라면_채팅_provider를_통해_메시지를_생성한다() throws Exception { + // given + given(providerComposite.findProvider(TextMessageType.CHATTINGS)).willReturn(provider); + given(session.getAttributes()).willReturn(세션_attribute_정보); + given(provider.handleCreateSendMessage(any(WebSocketSession.class), anyMap())) + .willReturn(List.of(new SendMessageDto(session, 전송할_메시지))); + + // when + final TextMessage message = new TextMessage(new ObjectMapper().writeValueAsString(세션_attribute_정보)); + webSocketHandler.handleTextMessage(session, message); + + // then + verify(provider, times(1)).handleCreateSendMessage(any(WebSocketSession.class), anyMap()); + verify(session, times(1)).sendMessage(any()); + } + + @Test + void 웹소켓_통신이_종료되면_해당_세션의_타입에_따라_해당하는_provider를_통해_세션을_제거한다() { + // given + given(providerComposite.findProvider(TextMessageType.CHATTINGS)).willReturn(provider); + given(session.getAttributes()).willReturn(세션_attribute_정보); + + // when + webSocketHandler.afterConnectionClosed(session, null); + + // then + verify(provider, times(1)).remove(any(WebSocketSession.class)); + } +} diff --git a/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/fixture/WebSocketHandlerTestFixture.java b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/fixture/WebSocketHandlerTestFixture.java new file mode 100644 index 000000000..59c7d7b3d --- /dev/null +++ b/backend/ddang/src/test/java/com/ddang/ddang/websocket/handler/fixture/WebSocketHandlerTestFixture.java @@ -0,0 +1,20 @@ +package com.ddang.ddang.websocket.handler.fixture; + +import com.ddang.ddang.websocket.handler.dto.TextMessageType; +import org.springframework.web.socket.TextMessage; + +import java.util.HashMap; +import java.util.Map; + +@SuppressWarnings("NonAsciiCharacters") +public class WebSocketHandlerTestFixture { + + protected Long 사용자_아이디 = 1L; + protected Map 세션_attribute_정보 = new HashMap<>( + Map.of( + "type", TextMessageType.CHATTINGS.name(), + "data", Map.of("userId", 사용자_아이디, "baseUrl", "/images") + ) + ); + protected TextMessage 전송할_메시지 = new TextMessage("메시지"); +}