Skip to content

Commit

Permalink
test: 테스트 추가
Browse files Browse the repository at this point in the history
  • Loading branch information
JJ503 committed Mar 19, 2024
1 parent b3d6d12 commit 6c0325b
Show file tree
Hide file tree
Showing 11 changed files with 462 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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<Long, WebSocketSessions> chatRoomSessions;

public WebSocketChatSessions() {
this.chatRoomSessions = new ConcurrentHashMap<>();
}
private final Map<Long, WebSocketSessions> chatRoomSessions = new ConcurrentHashMap<>();

public void add(final WebSocketSession session, final Long chatRoomId) {
chatRoomSessions.putIfAbsent(chatRoomId, new WebSocketSessions());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<WebSocketSession> sessions;

public WebSocketSessions() {
this.sessions = Collections.newSetFromMap(new ConcurrentHashMap<>());
}
private final Set<WebSocketSession> 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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ public TextMessageType supportTextMessageType() {
public List<SendMessageDto> handleCreateSendMessage(
final WebSocketSession session,
final Map<String, String> data
) throws Exception {
) throws JsonProcessingException {
final SessionAttributeDto sessionAttribute = getSessionAttributes(session);
final ChatMessageDataDto messageData = objectMapper.convertValue(data, ChatMessageDataDto.class);
sessions.add(session, messageData.chatRoomId());
Expand Down
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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<String, Object> 세션_attribute_정보 = new HashMap<>(Map.of("userId", 사용자_아이디, "baseUrl", "/images"));
protected Long 채팅방_아이디 = 1L;
}
Original file line number Diff line number Diff line change
@@ -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<SendMessageDto> 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<SendMessageDto> 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<SendMessageDto> 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();
}
}
Loading

0 comments on commit 6c0325b

Please sign in to comment.