java - Spring WebSocket 集成测试随机工作
问题描述
我有一个非常简单的 SpringBoot 项目,它具有简单的配置和简单的集成测试来测试 WebSockets。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>sandbox.websocket</groupId>
<artifactId>websocket</artifactId>
<version>1.0-SNAPSHOT</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.2.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<properties>
<java.version>1.8</java.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
SpringBoot应用程序:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
消息代理配置
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/topic");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/greeting")
.withSockJS();
}
}
集成测试以简单地连接到服务器、订阅消息代理并发送消息。
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
public class WebSocketIntegrationTest {
@LocalServerPort
private int localServerPort;
private BlockingQueue<String> blockingQueue;
@Before
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
}
@Test
public void shouldReceiveAMessageFromTheServer() throws Exception {
String uri = "ws://localhost:" + localServerPort + "/greeting";
WebSocketStompClient stompClient = new WebSocketStompClient(
new SockJsClient(Collections.singletonList(
new WebSocketTransport(
new StandardWebSocketClient()))));
String message = "MESSAGE TEST";
ListenableFuture<StompSession> connect = stompClient.connect(uri, new StompSessionHandlerAdapter() {});
StompSession session = connect.get(1, SECONDS);
session.subscribe("/topic", new DefaultStompFrameHandler());
session.send("/topic", message.getBytes());
Assert.assertEquals(message, blockingQueue.poll(10, SECONDS));
}
class DefaultStompFrameHandler implements StompFrameHandler {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return byte[].class;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
System.out.println("=============================================================");
System.out.println(new String((byte[]) o));
System.out.println("=============================================================");
blockingQueue.offer(new String((byte[]) o));
}
}
}
如果我从 javascript 客户端运行它并对其进行测试,它就像一个魅力。如果我运行集成测试,它只会在某些时候起作用。问题是有时 DefaultStompFrameHandler.handleFrame() 方法没有被调用,因此没有任何东西保存到队列中并且断言失败。
我编写了一个 InboundChannel 拦截器来拦截帧并将命令打印到控制台,并且所有四个命令都被打印(CONNECT、SUBSCRIBE、SEND、DISCONNECT)。
因此,包括 SEND 在内的所有命令都会发送到服务器,但有时(60-70%)无论 queue.poll 超时设置多长时间,都不会使用 StompFrameHandler。
请问有什么帮助吗?
解决方案
推荐阅读
- ubuntu - 请求的格式不兼容合并,将合并到 mkv
- cassandra - 宽行、分区、集群列/键和分区键的概念是否存在于 Cassandra 的查询语言级别?
- python-3.x - 到达空列时停止循环
- c# - C# .NET DirectoryInfo : FileSystemInfo 类成员
- javascript - 尝试转换为驼峰大小写时,toUpperCase 在 for 循环中不起作用
- blazor - Blazor 动态设置 CSS 文件
- triggers - 当用户尝试删除或重新父流时触发 Perforce 触发器
- python - 使用 Numpy 求解线性方程组
- java - 使用 PDF2DOM 将 PDF 解析为 HTML 返回 NoSuchMethodError
- r - addWMSTiles 不渲染