繁体   English   中英

Spring Boot如何测试Netty Handler?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM