Websocket Returns 空的单元测试
Unit Test For Websocket Returns Null
我正在尝试使用 JUnit
.
对 Springboot
中的 Websocket
实施单元测试
我正在关注 this link 它运行良好但结果为空,当我使用浏览器测试我的 websocket 时它发送了期望的结果。
让我展示一下我的测试class
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes =Main.class)
@WebAppConfiguration
public class WebSocketTest {
static final String WEBSOCKET_URI = "http://localhost:8080/api/realtimedata";
static final String WEBSOCKET_TOPIC = "/realtimedata";
BlockingQueue<WebSocketData> blockingQueue;
WebSocketStompClient stompClient;
@BeforeEach
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
stompClient = new WebSocketStompClient(new SockJsClient(
asList(new WebSocketTransport(new StandardWebSocketClient()))));
}
@Test
public void shouldReceiveAMessageFromTheServer() throws Exception {
StompSession session = stompClient
.connect(WEBSOCKET_URI, new StompSessionHandlerAdapter() {})
.get(1, SECONDS);
session.subscribe(WEBSOCKET_TOPIC, new DefaultStompFrameHandler());
String message = "{\"groupId\":\"grp-1\", \"accountId\":\"acc-1\", \"userId\":\"usr-1\"}";
session.send(WEBSOCKET_TOPIC, message.getBytes());
Assertions.assertEquals("trying to figureout", blockingQueue.poll(1, SECONDS));
}
class DefaultStompFrameHandler implements StompFrameHandler {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return WebSocketData.class;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
blockingQueue.offer((WebSocketData) o);
}
}
}
这是我的WebSocketConfiguration
class
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/realtimedata");
registry.setApplicationDestinationPrefixes("/wsconn");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/realtimedata")
.setAllowedOrigins("*")
.withSockJS();
}
}
这是我从服务器得到的响应
org.opentest4j.AssertionFailedError:
Expected :trying to figureout
Actual :null
更新:
在下面的答案中添加 Rieckpil
推荐的更改后,经过进一步研究,我的测试 class 现在看起来像这样
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ServerWebSocketTest {
@LocalServerPort
private Integer port;
static final String WEBSOCKET_TOPIC = "/realtimedata";
BlockingQueue<WebSocketData> blockingQueue;
WebSocketStompClient stompClient;
@BeforeEach
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
stompClient = new WebSocketStompClient(new SockJsClient(
asList(new WebSocketTransport(new StandardWebSocketClient()))));
// might be required
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());
String message = "{\"groupId\":\"grp-1\", \"accountId\":\"acc-1\", \"userId\":\"usr-1\"}";
session.send(WEBSOCKET_TOPIC, message.getBytes());
Assertions.assertEquals("trying to figureout", blockingQueue.poll(1, TimeUnit.SECONDS));
}
class DefaultStompFrameHandler **extends StompSessionHandlerAdapter**{
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return WebSocketData.class;
}
@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();
}**
}
private String getWsPath() {
return String.format("ws://localhost:%d/location_services/realtimedata", port);
}
}
进行这些更改后,我现在可以在日志中打印堆栈跟踪
这是我在这些更改后得到的异常
org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Cannot construct instance of `com.convo.locationservices.websocket.WebSocketData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==')
at [Source: (byte[])""eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==""; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.convo.locationservices.websocket.WebSocketData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==')
at [Source: (byte[])""eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==""; line: 1, column: 1], failedMessage=GenericMessage [payload=byte[82], headers={simpMessageType=MESSAGE, stompCommand=MESSAGE, nativeHeaders={destination=[/realtimedata], content-type=[application/json], subscription=[0], message-id=[cc55448f0b4f447d8f6bc7662acd15db-0], content-length=[82]}, simpSubscriptionId=0, contentType=application/json, simpSessionId=2df73ca0-e13b-c479-4591-37e9f7e8d689, simpDestination=/realtimedata}]
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:235)
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:197)
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:188)
at org.springframework.messaging.simp.stomp.DefaultStompSession.invokeHandler(DefaultStompSession.java:477)
at org.springframework.messaging.simp.stomp.DefaultStompSession.handleMessage(DefaultStompSession.java:429)
at org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter.handleMessage(WebSocketStompClient.java:340)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleMessageFrame(AbstractClientSockJsSession.java:294)
at org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleFrame(AbstractClientSockJsSession.java:230)
at org.springframework.web.socket.sockjs.client.WebSocketTransport$ClientSockJsWebSocketHandler.handleTextMessage(WebSocketTransport.java:163)
at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:114)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access[=15=]0(StandardWebSocketHandlerAdapter.java:43)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onMessage(StandardWebSocketHandlerAdapter.java:85)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onMessage(StandardWebSocketHandlerAdapter.java:82)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:95)
at org.apache.tomcat.websocket.WsFrameClient.resumeProcessing(WsFrameClient.java:209)
at org.apache.tomcat.websocket.WsFrameClient.access0(WsFrameClient.java:31)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.doResumeProcessing(WsFrameClient.java:186)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:163)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:148)
at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
at java.base/sun.nio.ch.Invoker.run(Invoker.java:219)
at java.base/sun.nio.ch.AsynchronousChannelGroupImpl.run(AsynchronousChannelGroupImpl.java:112)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.convo.locationservices.websocket.WebSocketData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==')
at [Source: (byte[])""eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==""; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1432)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1062)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1373)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3309)
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:219)
... 31 more
org.opentest4j.AssertionFailedError:
Expected :trying to figureout
Actual :null
任何人都可以指导我我做错了什么吗?
谢谢。
您应该将集成测试配置为使用启动的 Spring 上下文并且不要硬编码 8080
。
此外,请确保为您的 WebSocketStompClient
配置了适合您的用例的 MessageConverter
。默认值为 SimpleMessageConverter
。当您发送 byte[]
时,ByteArrayMessageConverter
应该适合。
您的测试可以重构为以下内容:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
@LocalServerPort
private Integer port;
static final String WEBSOCKET_TOPIC = "/realtimedata";
BlockingQueue<WebSocketData> blockingQueue;
WebSocketStompClient stompClient;
@BeforeEach
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
stompClient = new WebSocketStompClient(new SockJsClient(
asList(new WebSocketTransport(new StandardWebSocketClient()))));
webSocketStompClient.setMessageConverter(new ByteArrayMessageConverter());
}
@Test
public void shouldReceiveAMessageFromTheServer() throws Exception {
StompSession session = stompClient
.connect(getWsPath(), new StompSessionHandlerAdapter() {
})
.get(1, SECONDS);
session.subscribe(WEBSOCKET_TOPIC, new DefaultStompFrameHandler());
String message = "{\"groupId\":\"grp-1\", \"accountId\":\"acc-1\", \"userId\":\"usr-1\"}";
session.send(WEBSOCKET_TOPIC, message.getBytes());
Assertions.assertEquals("trying to figureout", blockingQueue.poll(1, SECONDS));
}
class DefaultStompFrameHandler implements StompFrameHandler {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return WebSocketData.class;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
blockingQueue.offer((WebSocketData) o);
}
}
private String getWsPath() {
return String.format("ws://localhost:%d/api/realtimedata", port);
}
}
此测试将启动整个 Spring 上下文、随机端口上的嵌入式 servlet 容器,并尝试连接到您的端点。
我遇到了同样的问题。就我而言,我忘记添加默认构造函数和所有参数构造函数
请检查您的 WebSocketData class 以添加构造函数
我正在尝试使用 JUnit
.
Springboot
中的 Websocket
实施单元测试
我正在关注 this link 它运行良好但结果为空,当我使用浏览器测试我的 websocket 时它发送了期望的结果。
让我展示一下我的测试class
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes =Main.class)
@WebAppConfiguration
public class WebSocketTest {
static final String WEBSOCKET_URI = "http://localhost:8080/api/realtimedata";
static final String WEBSOCKET_TOPIC = "/realtimedata";
BlockingQueue<WebSocketData> blockingQueue;
WebSocketStompClient stompClient;
@BeforeEach
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
stompClient = new WebSocketStompClient(new SockJsClient(
asList(new WebSocketTransport(new StandardWebSocketClient()))));
}
@Test
public void shouldReceiveAMessageFromTheServer() throws Exception {
StompSession session = stompClient
.connect(WEBSOCKET_URI, new StompSessionHandlerAdapter() {})
.get(1, SECONDS);
session.subscribe(WEBSOCKET_TOPIC, new DefaultStompFrameHandler());
String message = "{\"groupId\":\"grp-1\", \"accountId\":\"acc-1\", \"userId\":\"usr-1\"}";
session.send(WEBSOCKET_TOPIC, message.getBytes());
Assertions.assertEquals("trying to figureout", blockingQueue.poll(1, SECONDS));
}
class DefaultStompFrameHandler implements StompFrameHandler {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return WebSocketData.class;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
blockingQueue.offer((WebSocketData) o);
}
}
}
这是我的WebSocketConfiguration
class
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfiguration implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.enableSimpleBroker("/realtimedata");
registry.setApplicationDestinationPrefixes("/wsconn");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/realtimedata")
.setAllowedOrigins("*")
.withSockJS();
}
}
这是我从服务器得到的响应
org.opentest4j.AssertionFailedError:
Expected :trying to figureout
Actual :null
更新:
在下面的答案中添加 Rieckpil
推荐的更改后,经过进一步研究,我的测试 class 现在看起来像这样
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class ServerWebSocketTest {
@LocalServerPort
private Integer port;
static final String WEBSOCKET_TOPIC = "/realtimedata";
BlockingQueue<WebSocketData> blockingQueue;
WebSocketStompClient stompClient;
@BeforeEach
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
stompClient = new WebSocketStompClient(new SockJsClient(
asList(new WebSocketTransport(new StandardWebSocketClient()))));
// might be required
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());
String message = "{\"groupId\":\"grp-1\", \"accountId\":\"acc-1\", \"userId\":\"usr-1\"}";
session.send(WEBSOCKET_TOPIC, message.getBytes());
Assertions.assertEquals("trying to figureout", blockingQueue.poll(1, TimeUnit.SECONDS));
}
class DefaultStompFrameHandler **extends StompSessionHandlerAdapter**{
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return WebSocketData.class;
}
@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();
}**
}
private String getWsPath() {
return String.format("ws://localhost:%d/location_services/realtimedata", port);
}
}
进行这些更改后,我现在可以在日志中打印堆栈跟踪
这是我在这些更改后得到的异常
org.springframework.messaging.converter.MessageConversionException: Could not read JSON: Cannot construct instance of `com.convo.locationservices.websocket.WebSocketData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==')
at [Source: (byte[])""eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==""; line: 1, column: 1]; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.convo.locationservices.websocket.WebSocketData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==')
at [Source: (byte[])""eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==""; line: 1, column: 1], failedMessage=GenericMessage [payload=byte[82], headers={simpMessageType=MESSAGE, stompCommand=MESSAGE, nativeHeaders={destination=[/realtimedata], content-type=[application/json], subscription=[0], message-id=[cc55448f0b4f447d8f6bc7662acd15db-0], content-length=[82]}, simpSubscriptionId=0, contentType=application/json, simpSessionId=2df73ca0-e13b-c479-4591-37e9f7e8d689, simpDestination=/realtimedata}]
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:235)
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:197)
at org.springframework.messaging.converter.AbstractMessageConverter.fromMessage(AbstractMessageConverter.java:188)
at org.springframework.messaging.simp.stomp.DefaultStompSession.invokeHandler(DefaultStompSession.java:477)
at org.springframework.messaging.simp.stomp.DefaultStompSession.handleMessage(DefaultStompSession.java:429)
at org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter.handleMessage(WebSocketStompClient.java:340)
at org.springframework.web.socket.handler.WebSocketHandlerDecorator.handleMessage(WebSocketHandlerDecorator.java:75)
at org.springframework.web.socket.handler.LoggingWebSocketHandlerDecorator.handleMessage(LoggingWebSocketHandlerDecorator.java:56)
at org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleMessageFrame(AbstractClientSockJsSession.java:294)
at org.springframework.web.socket.sockjs.client.AbstractClientSockJsSession.handleFrame(AbstractClientSockJsSession.java:230)
at org.springframework.web.socket.sockjs.client.WebSocketTransport$ClientSockJsWebSocketHandler.handleTextMessage(WebSocketTransport.java:163)
at org.springframework.web.socket.handler.AbstractWebSocketHandler.handleMessage(AbstractWebSocketHandler.java:43)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.handleTextMessage(StandardWebSocketHandlerAdapter.java:114)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.access[=15=]0(StandardWebSocketHandlerAdapter.java:43)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onMessage(StandardWebSocketHandlerAdapter.java:85)
at org.springframework.web.socket.adapter.standard.StandardWebSocketHandlerAdapter.onMessage(StandardWebSocketHandlerAdapter.java:82)
at org.apache.tomcat.websocket.WsFrameBase.sendMessageText(WsFrameBase.java:395)
at org.apache.tomcat.websocket.WsFrameBase.processDataText(WsFrameBase.java:495)
at org.apache.tomcat.websocket.WsFrameBase.processData(WsFrameBase.java:294)
at org.apache.tomcat.websocket.WsFrameBase.processInputBuffer(WsFrameBase.java:133)
at org.apache.tomcat.websocket.WsFrameClient.processSocketRead(WsFrameClient.java:95)
at org.apache.tomcat.websocket.WsFrameClient.resumeProcessing(WsFrameClient.java:209)
at org.apache.tomcat.websocket.WsFrameClient.access0(WsFrameClient.java:31)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.doResumeProcessing(WsFrameClient.java:186)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:163)
at org.apache.tomcat.websocket.WsFrameClient$WsFrameClientCompletionHandler.completed(WsFrameClient.java:148)
at java.base/sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:127)
at java.base/sun.nio.ch.Invoker.run(Invoker.java:219)
at java.base/sun.nio.ch.AsynchronousChannelGroupImpl.run(AsynchronousChannelGroupImpl.java:112)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `com.convo.locationservices.websocket.WebSocketData` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==')
at [Source: (byte[])""eyJncm91cElkIjoiZ3JwLTEiLCAiYWNjb3VudElkIjoiYWNjLTEiLCAidXNlcklkIjoidXNyLTEifQ==""; line: 1, column: 1]
at com.fasterxml.jackson.databind.exc.MismatchedInputException.from(MismatchedInputException.java:63)
at com.fasterxml.jackson.databind.DeserializationContext.reportInputMismatch(DeserializationContext.java:1432)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1062)
at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:371)
at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:323)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1373)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:171)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:161)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4218)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3309)
at org.springframework.messaging.converter.MappingJackson2MessageConverter.convertFromInternal(MappingJackson2MessageConverter.java:219)
... 31 more
org.opentest4j.AssertionFailedError:
Expected :trying to figureout
Actual :null
任何人都可以指导我我做错了什么吗?
谢谢。
您应该将集成测试配置为使用启动的 Spring 上下文并且不要硬编码 8080
。
此外,请确保为您的 WebSocketStompClient
配置了适合您的用例的 MessageConverter
。默认值为 SimpleMessageConverter
。当您发送 byte[]
时,ByteArrayMessageConverter
应该适合。
您的测试可以重构为以下内容:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
@LocalServerPort
private Integer port;
static final String WEBSOCKET_TOPIC = "/realtimedata";
BlockingQueue<WebSocketData> blockingQueue;
WebSocketStompClient stompClient;
@BeforeEach
public void setup() {
blockingQueue = new LinkedBlockingDeque<>();
stompClient = new WebSocketStompClient(new SockJsClient(
asList(new WebSocketTransport(new StandardWebSocketClient()))));
webSocketStompClient.setMessageConverter(new ByteArrayMessageConverter());
}
@Test
public void shouldReceiveAMessageFromTheServer() throws Exception {
StompSession session = stompClient
.connect(getWsPath(), new StompSessionHandlerAdapter() {
})
.get(1, SECONDS);
session.subscribe(WEBSOCKET_TOPIC, new DefaultStompFrameHandler());
String message = "{\"groupId\":\"grp-1\", \"accountId\":\"acc-1\", \"userId\":\"usr-1\"}";
session.send(WEBSOCKET_TOPIC, message.getBytes());
Assertions.assertEquals("trying to figureout", blockingQueue.poll(1, SECONDS));
}
class DefaultStompFrameHandler implements StompFrameHandler {
@Override
public Type getPayloadType(StompHeaders stompHeaders) {
return WebSocketData.class;
}
@Override
public void handleFrame(StompHeaders stompHeaders, Object o) {
blockingQueue.offer((WebSocketData) o);
}
}
private String getWsPath() {
return String.format("ws://localhost:%d/api/realtimedata", port);
}
}
此测试将启动整个 Spring 上下文、随机端口上的嵌入式 servlet 容器,并尝试连接到您的端点。
我遇到了同样的问题。就我而言,我忘记添加默认构造函数和所有参数构造函数
请检查您的 WebSocketData class 以添加构造函数