【问题标题】:How to Receive Response from Websocket Unit Test in Springboot如何在 Spring Boot 中接收来自 Websocket 单元测试的响应
【发布时间】:2020-11-09 10:49:17
【问题描述】:

我是 websockets 新手,我正在尝试编写单元测试。

我的单元测试运行良好,但有以下两个问题

  1. 不知道为什么,但它迫使我期待作为输入(即 WebSocketRequestData)发送到 websocket 的相同对象,而不是来自 websocket 的实际响应,即 WebSocketData

  2. 它返回一个空对象作为结果,因此它通过 NotNull 断言。

谁能帮我解开这个困惑!

在单元测试中从我的 websocket 获得响应的正确方法是什么?

这是我的 websocketTest 类的代码

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ServerWebSocketTest {

@LocalServerPort
private Integer port;

static final String WEBSOCKET_TOPIC = "/user/locationrealtimedata/item" ;

BlockingQueue<WebSocketRequestData> blockingQueue;
WebSocketStompClient stompClient;

@BeforeEach
public void setup() {

    blockingQueue = new LinkedBlockingDeque<>();
    stompClient = new WebSocketStompClient(new SockJsClient(
            asList(new WebSocketTransport(new StandardWebSocketClient()))));
    
    stompClient.setMessageConverter(new MappingJackson2MessageConverter());

}

@Test
public void shouldReceiveAMessageFromTheServer() throws Exception {
    StompSession session = stompClient
            .connect(getWsPath(), new DefaultStompFrameHandler() {
            })
            .get(1, TimeUnit.SECONDS);
    session.subscribe(WEBSOCKET_TOPIC, new DefaultStompFrameHandler());

    WebSocketRequestData webSocketRequestData = new WebSocketRequestData();
    webSocketRequestData.setUserId("usr-1");
    webSocketRequestData.setAccountId("acc-1");
    webSocketRequestData.setGroupId("grp-1");
    session.send("/wsconn/start", webSocketRequestData);
    WebSocketRequestData responseObj = blockingQueue.poll(15, TimeUnit.SECONDS);
    Assertions.assertNotNull(responseObj);

}

class DefaultStompFrameHandler extends StompSessionHandlerAdapter{   
    @Override
    public Type getPayloadType(StompHeaders stompHeaders) {
        return WebSocketRequestData.class;
    }

    @Override
    public void handleFrame(StompHeaders stompHeaders, Object o) {
        blockingQueue.offer((WebSocketRequestData) o); // instead of **WebSocketData** it forces me to add casting for **WebSocketRequestData**
    }


    @Override
    public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {
        exception.printStackTrace();
    }


}

private String getWsPath() {
    return String.format("ws://localhost:%d/location_services/locationrealtimedata", port);
}

}

提前致谢

【问题讨论】:

    标签: spring-boot websocket junit5 spring-websocket spring-boot-test


    【解决方案1】:

    您不必为输入和响应类型使用相同的 Java 类。

    请求类型是您在 session.send("/endpoint", payload); 中使用的类型,在您的情况下是 WebSocketRequestData

    WebSocketRequestData webSocketRequestData = new WebSocketRequestData();
    webSocketRequestData.setUserId("usr-1");
    webSocketRequestData.setAccountId("acc-1");
    webSocketRequestData.setGroupId("grp-1");
    session.send("/wsconn/start", webSocketRequestData);
    

    在使用消息时,您指定实现StompFrameHandler 和覆盖getPayloadType 时期望的实际响应类型。

    因此,不要实现StompSessionHandlerAdapter,而是使用StompFrameHandler 接口并将其实现如下:

    class DefaultStompFrameHandler extends StompSessionHandlerAdapter{   
        @Override
        public Type getPayloadType(StompHeaders stompHeaders) {
            return WebSocketData.class; // or any other class your expect
        }
    
        @Override
        public void handleFrame(StompHeaders stompHeaders, Object o) {
            blockingQueue.offer((WebSocketData) o); 
        }
    
        @Override
        public void handleException(StompSession session, StompCommand command, StompHeaders headers, byte[] payload, Throwable exception) {
            exception.printStackTrace();
        }
    
    }
    

    还要确保您的 BlockingQueue 使用正确的类型 BlockingQueue&lt;WebSocketData&gt; blockingQueue

    【讨论】:

    • 成功了,感谢您投入时间和精力,非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 2017-02-08
    • 2016-05-28
    • 2020-04-04
    • 2016-03-29
    • 1970-01-01
    相关资源
    最近更新 更多