如何对Netty处理程序进行单元测试

14

我实现了一个扩展了SimpleChannelHandler的处理程序,并覆盖了一些方法,例如channelConnected、messageReceived等。然而,我想知道如何对其进行单元测试?

我搜索了有关“netty单元测试”的内容,并发现了一篇文章,其中提到了考虑CodecEmbedder,但我仍然不确定如何开始。您有任何示例或建议可以用来对Netty代码进行单元测试吗?

非常感谢。

1个回答

19

在Netty中,有不同的方法来测试您的网络堆栈。

测试ChannelHandlers

您可以使用Netty的EmbeddedChannel来模拟用于测试的Netty连接,例如:

@Test
public void nettyTest() {
    EmbeddedChannel channel = new EmbeddedChannel(new StringDecoder(StandardCharsets.UTF_8));
    channel.writeInbound(Unpooled.wrappedBuffer(new byte[]{(byte)0xE2,(byte)0x98,(byte)0xA2}));
    String myObject = channel.readInbound();
    // Perform checks on your object
    assertEquals("☢", myObject);
}

此测试旨在测试StringDecoder解码Unicode的能力是否正确(由我发布的此错误的示例)。

您还可以使用EmbeddedChannel测试编码器方向,对此,您应该使用writeOutBoundreadInbound

更多示例:

DelimiterBasedFrameDecoderTest.java:

@Test
public void testIncompleteLinesStrippedDelimiters() {
    EmbeddedChannel ch = new EmbeddedChannel(new DelimiterBasedFrameDecoder(8192, true,
            Delimiters.lineDelimiter()));
    ch.writeInbound(Unpooled.copiedBuffer("Test", Charset.defaultCharset()));
    assertNull(ch.readInbound());
    ch.writeInbound(Unpooled.copiedBuffer("Line\r\ng\r\n", Charset.defaultCharset()));
    assertEquals("TestLine", releaseLater((ByteBuf) ch.readInbound()).toString(Charset.defaultCharset()));
    assertEquals("g", releaseLater((ByteBuf) ch.readInbound()).toString(Charset.defaultCharset()));
    assertNull(ch.readInbound());
    ch.finish();
}

更多示例请参考Github。

ByteBuf

为了测试是否正确使用了ByteBuf,您可以设置一个JVM参数来检查泄漏的ByteBuf。为此,您应该将-Dio.netty.leakDetectionLevel=PARANOID添加到启动参数中,或调用方法ResourceLeakDetector.setLevel(PARANOID)


我花了一点时间才明白它,但我让它工作了。我只是用我的ChannelHandler替换了EmbeddedChannel构造函数中的参数。你有找到不重复这么多代码的方法吗?我的意思是... channel = new EmbeddedChannel(new MessageHandler1()); channel = new EmbeddedChannel(new MessageHandler2()); 等等... - Sebastian D'Agostino
谢谢!我已经使用Netty一段时间了,除了设置服务器之外,从未知道如何测试我的处理程序逻辑!这将节省我很多时间!!!!!! - Mr00Anderson
1
@Ferrybig,你展示的测试和Github链接中的一些示例是有意义的,因为你正在测试特定的网络协议或某个规则。但如果我有一个AuthHandler,它有一个验证用户的authService,那么像这样执行其他业务逻辑操作的处理程序怎么办呢?我已经为authService编写了单元测试,但本质上channelReadComplete只是调用了authService.validate(user)。这些场景仍然可以进行测试吗? - Crystal
当使用 ResourceLeakDetector.setLevel(PARANOID) 时,您建议我们如何通过或失败测试? - Dave Moten
@Ferrybig 给了我很大的帮助。谢谢!! - Srini

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接