测试几个对 websocket 的调用

Posted

技术标签:

【中文标题】测试几个对 websocket 的调用【英文标题】:Test several calls to websocket 【发布时间】:2022-01-16 11:20:42 【问题描述】:

我第一次尝试在春天跺脚。我创建了一个类似于this的端点

@MessageMapping("/game")
@SendTo("/topic/status")
public GameStatus greeting(GameMessage message, SimpMessageHeaderAccessor 
 headerAccessor) throws Exception 

哪个(长话短说)返回持久数据。

和教程类似,我是这样测试的

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GameIntegrationTests 

    @LocalServerPort
    private int port;

    private SockJsClient sockJsClient;

    private WebSocketStompClient stompClient;

    private final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();

    @BeforeEach
    public void setup() 
        List<Transport> transports = new ArrayList<>();
        transports.add(new WebSocketTransport(new StandardWebSocketClient()));
        this.sockJsClient = new SockJsClient(transports);

        this.stompClient = new WebSocketStompClient(sockJsClient);
        this.stompClient.setMessageConverter(new MappingJackson2MessageConverter());
    

    @Test
    public void getGame() throws Exception 

        final CountDownLatch latch = new CountDownLatch(1);
        final AtomicReference<Throwable> failure = new AtomicReference<>();

        String[] board =  "1", "2", "X", "4", "5", "6", "7", "8", "9" ;
        StompSessionHandler handlerPlayer = playerHandler(latch, failure, 3, board);

        this.stompClient.connect("ws://localhost:port/tictactoe-websocket", this.headers, handlerPlayer, this.port);

        if (latch.await(3, TimeUnit.SECONDS)) 
            if (failure.get() != null) 
                throw new AssertionError("", failure.get());
            
         else 
            fail("Status not received");
        

    

    private StompSessionHandler playerHandler(CountDownLatch latch, AtomicReference<Throwable> failure, Integer postion,
            String[] board) 
        return new TestSessionHandler(failure) 

            @Override
            public void afterConnected(final StompSession session, StompHeaders connectedHeaders) 
                session.subscribe("/topic/status", new StompFrameHandler() 
                    @Override
                    public Type getPayloadType(StompHeaders headers) 
                        return GameStatus.class;
                    

                    @Override
                    public void handleFrame(StompHeaders headers, Object payload) 
                        GameStatus gameStatus = (GameStatus) payload;
                        try 

                            assertArrayEquals(board, gameStatus.getBoard());
                         catch (Throwable t) 
                            failure.set(t);
                         finally 
                            session.disconnect();
                            latch.countDown();
                        
                    
                );
                try 
                    session.send("/app/game", new GameMessage("Spring", postion));
                 catch (Throwable t) 
                    failure.set(t);
                    latch.countDown();
                
            
        ;
    

    private class TestSessionHandler extends StompSessionHandlerAdapter 

        private final AtomicReference<Throwable> failure;

        public TestSessionHandler(AtomicReference<Throwable> failure) 
            this.failure = failure;
        

        @Override
        public void handleFrame(StompHeaders headers, Object payload) 
            this.failure.set(new Exception(headers.toString()));
        

        @Override
        public void handleException(StompSession s, StompCommand c, StompHeaders h, byte[] p, Throwable ex) 
            this.failure.set(ex);
        

        @Override
        public void handleTransportError(StompSession session, Throwable ex) 
            this.failure.set(ex);
        
    

我想在同一个测试中测试第二次调用同一个端点来实现

 boolean status= false;
 StompSessionHandler handlerPlayer1 = playerHandler(latch, failure, 5, status);

关于我该怎么做的任何提示?提前致谢

【问题讨论】:

【参考方案1】:

我更改了代码,它可以工作,但看起来有点矫枉过正。让我知道这看起来是否正常

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class GameIntegrationTests 

    @LocalServerPort
    private int port;

    private WebSocketStompClient stompClientPlayerOne;
    private WebSocketStompClient stompClientPlayerTwo;

    private final WebSocketHttpHeaders headers = new WebSocketHttpHeaders();

    @BeforeEach
    public void setup() 
        this.stompClientPlayerOne = createClient();
        this.stompClientPlayerTwo = createClient();
    

    @Test
    public void getGame() throws Exception 

        String[] board =  "1", "2", "X", "4", "5", "6", "7", "8", "9" ;
        testNewConnection(board, 3, stompClientPlayerOne);

        String[] board1 =  "1", "2", "X", "4", "5", "6", "O", "8", "9" ;
        testNewConnection(board1, 7, stompClientPlayerTwo);

    

    private void testNewConnection(String[] board, Integer position, WebSocketStompClient stompClient)
            throws InterruptedException, AssertionError 
        final CountDownLatch latch = new CountDownLatch(1);
        final AtomicReference<Throwable> failure = new AtomicReference<>();
        StompSessionHandler handlerPlayer = playerHandler(latch, failure, position, board);
        stompClient.connect("ws://localhost:port/tictactoe-websocket", this.headers, handlerPlayer, this.port);
        waitIfFailure(latch, failure);
    

    private void waitIfFailure(CountDownLatch latch, AtomicReference<Throwable> failure)
            throws InterruptedException, AssertionError 
        if (latch.await(3, TimeUnit.SECONDS)) 
            if (failure.get() != null) 
                throw new AssertionError("", failure.get());
            
         else 
            fail("Status not received");
        
    

    private StompSessionHandler playerHandler(CountDownLatch latch, AtomicReference<Throwable> failure, Integer postion,
            String[] board) 
        return new TestSessionHandler(failure) 

            @Override
            public void afterConnected(final StompSession session, StompHeaders connectedHeaders) 
                session.subscribe("/topic/status", new StompFrameHandler() 
                    @Override
                    public Type getPayloadType(StompHeaders headers) 
                        return GameStatus.class;
                    

                    @Override
                    public void handleFrame(StompHeaders headers, Object payload) 
                        GameStatus gameStatus = (GameStatus) payload;
                        try 

                            assertArrayEquals(board, gameStatus.getBoard());
                         catch (Throwable t) 
                            failure.set(t);
                         finally 
                            session.disconnect();
                            latch.countDown();
                        
                    
                );
                try 
                    session.send("/app/game", new GameMessage("Spring", postion));
                 catch (Throwable t) 
                    failure.set(t);
                    latch.countDown();
                
            
        ;
    

    private WebSocketStompClient createClient() 
        List<Transport> transports = new ArrayList<>();
        transports.add(new WebSocketTransport(new StandardWebSocketClient()));
        var sockJsClient = new SockJsClient(transports);

        var stompClient = new WebSocketStompClient(sockJsClient);
        stompClient.setMessageConverter(new MappingJackson2MessageConverter());
        return stompClient;
    

    private class TestSessionHandler extends StompSessionHandlerAdapter 

        private final AtomicReference<Throwable> failure;

        public TestSessionHandler(AtomicReference<Throwable> failure) 
            this.failure = failure;
        

        @Override
        public void handleFrame(StompHeaders headers, Object payload) 
            this.failure.set(new Exception(headers.toString()));
        

        @Override
        public void handleException(StompSession s, StompCommand c, StompHeaders h, byte[] p, Throwable ex) 
            this.failure.set(ex);
        

        @Override
        public void handleTransportError(StompSession session, Throwable ex) 
            this.failure.set(ex);
        
    

【讨论】:

以上是关于测试几个对 websocket 的调用的主要内容,如果未能解决你的问题,请参考以下文章

springboot websocket全套模板,省去搭建的烦恼,还有福利拿哦

springboot websocket全套模板,省去搭建的烦恼,还有福利拿哦

使用rabbitmq广播模式来处理集群下的websocket消息推送

webSocket 简单介绍

几个对程序员的误解,害人不浅!

如何将 spring-data-rest 与 spring websocket 混合到一个实现中