[英]Spring Boot how to test Netty Handler?
我有一个带有 Spring Boot 2.3.1
的 Netty TCP 服务器。
我一直在寻找许多资源来测试 Netty 的处理程序,比如
但是,它对我不起作用。
对于 EmbeddedChannel,我有以下错误 - Your remote address is embedded.
这是代码:
@ActiveProfiles("test")
@RunWith(MockitoJUnitRunner.class)
public class ProcessingHandlerTest_Embedded {
@Mock
private PermissionService permissionService;
private EmbeddedChannel embeddedChannel;
private final Gson gson = new Gson();
private ProcessingHandler processingHandler;
@Before
public void setUp() {
processingHandler = new ProcessingHandler(permissionService);
embeddedChannel = new EmbeddedChannel(processingHandler);
}
@Test
public void testHeartbeatMessage() {
// given
HeartbeatRequest heartbeatMessage = HeartbeatRequest.builder()
.messageID("heartbeat")
.build();
HeartbeatResponse response = HeartbeatResponse.builder()
.responseCode("ok")
.build();
String request = gson.toJson(heartbeatMessage).concat("\r\n");
String expected = gson.toJson(response).concat("\r\n");
// when
embeddedChannel.writeInbound(request);
// then
Queue<Object> outboundMessages = embeddedChannel.outboundMessages();
assertEquals(expected, outboundMessages.poll());
}
}
Output:
22:21:29.062 [main] INFO handler.ProcessingHandler - CLIENT_IP: embedded
22:21:29.062 [main] INFO handler.ProcessingHandler - CLIENT_REQUEST: {"messageID":"heartbeat"}
22:21:29.067 [main] DEBUG handler.ProcessingHandler - heartbeat request: HeartbeatRequest(messageID=heartbeat)
org.junit.ComparisonFailure:
<Click to see difference>
我尝试了一些带有远程地址的东西:
@ActiveProfiles("test")
@RunWith(MockitoJUnitRunner.class)
public class ProcessingHandlerTest {
@Mock
private PermissionService permissionService;
private final Gson gson = new Gson();
private ProcessingHandler processingHandler;
@Mock
private ChannelHandlerContext channelHandlerContext;
@Mock
private Channel channel;
@Mock
private SocketAddress remoteAddress;
@Before
public void setUp() {
processingHandler = new ProcessingHandler(permissionService);
when(channelHandlerContext.channel()).thenReturn(channel);
when(channelHandlerContext.channel().remoteAddress()).thenReturn(remoteAddress);
}
@Test
public void testHeartbeatMessage() {
// given
HeartbeatRequest heartbeatMessage = HeartbeatRequest.builder()
.messageID("heartbeat")
.build();
HeartbeatResponse response = HeartbeatResponse.builder()
.responseCode("ok")
.build();
String request = gson.toJson(heartbeatMessage).concat("\r\n");
String expected = gson.toJson(response).concat("\r\n");
// when
processingHandler.channelRead(channelHandlerContext, request);
// then
}
}
Output:
22:26:06.119 [main] INFO handler.ProcessingHandler - CLIENT_IP: null
22:26:06.124 [main] INFO handler.ProcessingHandler - CLIENT_REQUEST: {"messageID":"heartbeat"}
22:26:06.127 [main] DEBUG handler.ProcessingHandler - heartbeat request: HeartbeatRequest(messageID=heartbeat)
但是,我不知道如何对这种情况进行精确测试。
这是配置的一个片段:
@Bean
@SneakyThrows
public InetSocketAddress tcpSocketAddress() {
// for now, hostname is: localhost/127.0.0.1:9090
return new InetSocketAddress("localhost", nettyProperties.getTcpPort());
// for real client devices: A05264/172.28.1.162:9090
// return new InetSocketAddress(InetAddress.getLocalHost(), nettyProperties.getTcpPort());
}
@Component
@RequiredArgsConstructor
public class QrReaderChannelInitializer extends ChannelInitializer<SocketChannel> {
private final StringEncoder stringEncoder = new StringEncoder();
private final StringDecoder stringDecoder = new StringDecoder();
private final QrReaderProcessingHandler readerServerHandler;
private final NettyProperties nettyProperties;
@Override
protected void initChannel(SocketChannel socketChannel) {
ChannelPipeline pipeline = socketChannel.pipeline();
// Add the text line codec combination first
pipeline.addLast(new DelimiterBasedFrameDecoder(1024 * 1024, Delimiters.lineDelimiter()));
pipeline.addLast(new ReadTimeoutHandler(nettyProperties.getClientTimeout()));
pipeline.addLast(stringDecoder);
pipeline.addLast(stringEncoder);
pipeline.addLast(readerServerHandler);
}
}
处理程序是ChannelInboundHandlerAdapter
的典型实现,具有覆盖主要方法。
如何使用 Spring Boot 测试 Handler?
所以Your remote address is embedded.
与其说是错误,不如说是您收到的意外 output。
应该为 Spring Boot 编写 how.netty 测试没有什么特别之处。 作为示例,这是对始终输出“ok”的处理程序的最小测试:
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.util.CharsetUtil;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SpringBootTest
class DemoApplicationTests {
@Test
void testRoundTrip() {
// given
String request = "heartbeat";
// when
EmbeddedChannel embeddedChannel = new EmbeddedChannel(new OkResponder());
embeddedChannel.writeInbound(request);
// then
ByteBuf outboundMessage = embeddedChannel.readOutbound();
//(ByteBuf)embeddedChannel.outboundMessages().poll(), as you've used, works in the above line too.
assertEquals("ok", outboundMessage.toString(CharsetUtil.UTF_8));
}
static class OkResponder extends ChannelInboundHandlerAdapter {
@Override
public void channelReadComplete(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer("ok", CharsetUtil.UTF_8))
.addListener(ChannelFutureListener.CLOSE);
}
}
}
在我看来,您的ProcessingHandler
正在调用ctx.channel().remoteAddress()
在某个时候将为 EmbeddedChannel 返回“嵌入”,这会导致您看到的 output。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.