Caused by: java.lang.ClassCastException: class com.example.chat.dto.ChatMessage cannot be cast to class [B (com.example.chat.dto.ChatMessage is in unnamed module of loader 'app'; [B is in module java.base of loader 'bootstrap')
at org.springframework.web.socket.messaging.WebSocketStompClientWebSocketTcpConnectionHandlerAdapter.sendAsync(WebSocketStompClient.java:465)
at org.springframework.messaging.simp.stomp.DefaultStompSession.execute(DefaultStompSession.java:290)
... 107 more
다음 링크를 참조하여 websocket 테스트를 작성하는데, 계속 ClassCastException이 발생했다.
@BeforeEach
void init() throws ExecutionException, InterruptedException, TimeoutException {
webSocketStompClient = new WebSocketStompClient(
new SockJsClient(
List.of(new WebSocketTransport(new StandardWebSocketClient()))));
session = webSocketStompClient.connectAsync(
String.format("ws://localhost:%d/ws", port),
new StompSessionHandlerAdapter() {
})
.get(1000, TimeUnit.SECONDS);
webSocketStompClient.setMessageConverter(new MappingJackson2MessageConverter());
}
@Nested
@DisplayName("send 메서드는")
class DescribeSend {
@Nested
@DisplayName("유효한 값이 전달되면")
class ContextWithValidData {
@Test
@DisplayName("해당 토픽을 구독한 사용자들에게 메시지를 발행한다")
void ItPublishMessage() throws JsonProcessingException {
// given
String topicId = "topicId";
ChatMessage message = ChatMessage.from("hi~");
BlockingQueue<ChatMessage> queue = new ArrayBlockingQueue<>(1);
session.subscribe(String.format("/topic/%s", topicId), new StompFrameHandler() {
@Override
public Type getPayloadType(StompHeaders headers) {
return ChatMessage.class;
}
@Override
public void handleFrame(StompHeaders headers, Object payload) {
queue.add((ChatMessage) payload);
}
});
// when
StompHeaders stompHeaders = new StompHeaders();
stompHeaders.setDestination(String.format("/chat/%s/send", topicId));
stompHeaders.setContentType(APPLICATION_JSON);
session.send(stompHeaders, message);
// then
// await()
// .atMost(10, TimeUnit.SECONDS)
// .untilAsserted(() -> assertEquals(message.getMessage(), queue.poll()));
}
}
}
}
디버깅을 하며 쫓아가보니 다음의 코드에서 문제가 발생하고 있었다.
ChatMessage -> byte[] 로 변환하려고 하니 발생하는 문제라고 생각했다.
그래서 message 를 생성하는 코드를 디버깅해서 따라가봤다.
분명 메시지 컨버터를 MappingJackson2MessageConverter로 하였는데
기본 설정인 SimpleMessageConverter가 실행되는 게 이상했다.
따로 메시지 컨버터를 설정하지 않으면 기본으로 SimpleMessageConverter로 된다는 내용 참고
webSocketStompClient.setMessageConverter(new MappingJackson2MessageConverter());
그래서 메시지 컨버터 세팅 설정의 순서를 바꿔보니 정상적으로 동작했다.
기존코드
@BeforeEach
void init() throws ExecutionException, InterruptedException, TimeoutException {
webSocketStompClient = new WebSocketStompClient(
new SockJsClient(
List.of(new WebSocketTransport(new StandardWebSocketClient()))));
session = webSocketStompClient.connectAsync(
String.format("ws://localhost:%d/ws", port),
new StompSessionHandlerAdapter() {
})
.get(1000, TimeUnit.SECONDS);
webSocketStompClient.setMessageConverter(new MappingJackson2MessageConverter());
}
변경코드
@BeforeEach
void init() throws ExecutionException, InterruptedException, TimeoutException {
webSocketStompClient = new WebSocketStompClient(
new SockJsClient(
List.of(new WebSocketTransport(new StandardWebSocketClient()))));
webSocketStompClient.setMessageConverter(new MappingJackson2MessageConverter());
session = webSocketStompClient.connectAsync(
String.format("ws://localhost:%d/ws", port),
new StompSessionHandlerAdapter() {
})
.get(1000, TimeUnit.SECONDS);
}
테스트 성공