使用嵌入式通道测试 Netty
在本文中,我们将了解如何使用 EmbeddedChannel 来测试入站和出站通道处理程序的功能。
Netty 是一个非常通用的框架,用于编写高性能异步应用程序。如果没有合适的工具,对此类应用程序进行单元测试可能会很棘手。
值得庆幸的是,该框架为我们提供了EmbeddedChannel类 - 它有助于ChannelHandlers的测试。
2. Setup
EmbeddedChannel是 Netty 框架的一部分,因此唯一需要的依赖项是 Netty 本身的依赖项。
代码语言:javascript代码运行次数:0运行复制<dependency>
<groupId>ioty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.24.Final</version>
</dependency>
3. EmbeddedChannel概述
EmbeddedChannel类只是 AbstractChannel 的另一种实现,它无需真正的网络连接即可传输数据。
这很有用,因为我们可以通过在入站通道上写入数据来模拟传入消息,还可以在出站通道上检查生成的响应。通过这种方式,我们可以单独测试每个通道处理程序或在整个通道管道中。
要测试一个或多个通道处理程序,我们首先必须使用其构造函数之一创建一个嵌入式通道实例。
初始化嵌入式通道的最常见方法是将通道处理程序列表传递给其构造函数:
代码语言:javascript代码运行次数:0运行复制EmbeddedChannel channel = new EmbeddedChannel(
new HttpMessageHandler(), new CalculatorOperationHandler());
如果我们想更好地控制处理程序插入管道的顺序,我们可以创建一个使用默认构造函数的嵌入式通道并直接添加处理程序:
代码语言:javascript代码运行次数:0运行复制channel.pipeline()
.addFirst(new HttpMessageHandler())
.addLast(new CalculatorOperationHandler());
此外,当我们创建一个 EmbeddedChannel 时,它将具有由 DefaultChannelConfig类给出的默认配置。
当我们想要使用自定义配置时,例如将连接超时值从默认值降低,我们可以使用 config() 方法访问 ChannelConfig 对象:
代码语言:javascript代码运行次数:0运行复制DefaultChannelConfig channelConfig = (DefaultChannelConfig) channel
.config();
channelConfig.setConnectTimeoutMillis(500);
嵌入式通道包括我们可以用来读取和写入数据到我们的通道管道的方法。最常用的方法是:
- readInbound()
- readOutbound()
- writeInbound(Object… msgs)
- writeOutbound(Object… msgs)
读取方法检索并删除入站/出站队列中的第一个元素。当我们需要在不删除任何元素的情况下访问整个消息队列时,我们可以使用 outboundMessages() 方法:
代码语言:javascript代码运行次数:0运行复制Object lastOutboundMessage = channel.readOutbound();
Queue<Object> allOutboundMessages = channel.outboundMessages();
当消息成功添加到通道的入站/出站管道时,写入方法返回 true:
代码语言:javascript代码运行次数:0运行复制channel.writeInbound(httpRequest)
这个想法是,我们在入站管道上写入消息,以便输出通道处理程序将处理它们,并且我们希望结果可以从出站管道读取。
4. 测试通道处理程序
让我们看一个简单的示例,其中我们想要测试由两个接收 HTTP 请求的通道处理程序组成的管道,并期望包含计算结果的 HTTP 响应:
代码语言:javascript代码运行次数:0运行复制EmbeddedChannel channel = new EmbeddedChannel(
new HttpMessageHandler(), new CalculatorOperationHandler());
第一个,HttpMessageHandler 将从 HTTP 请求中提取数据,并将其传递给管道中的秒 ChannelHandler CalculatorOperationHandler,以处理数据。
现在,让我们编写 HTTP 请求,看看入站管道是否处理它:
代码语言:javascript代码运行次数:0运行复制FullHttpRequest httpRequest = new DefaultFullHttpRequest(
HttpVersion.HTTP_1_1, HttpMethod.GET, "/calculate?a=10&b=5");
httpRequest.headers().add("Operator", "Add");
assertThat(channel.writeInbound(httpRequest)).isTrue();
long inboundChannelResponse = channel.readInbound();
assertThat(inboundChannelResponse).isEqualTo(15);
我们可以看到,我们已经使用 writeInbound() 方法在入站管道上发送了 HTTP 请求,并使用 readInbound() 读取结果;inboundChannelResponse 是由我们发送的数据在入站管道中的所有通道处理程序处理后生成的消息。
现在,让我们检查一下我们的 Netty 服务器是否使用正确的 HTTP 响应消息进行响应。为此,我们将检查出站管道上是否存在消息:
代码语言:javascript代码运行次数:0运行复制assertThat(channel.outboundMessages().size()).isEqualTo(1);
在本例中,出站消息是 HTTP 响应,因此让我们检查内容是否正确。我们通过读取出站管道中的最后一条消息来执行此操作:
代码语言:javascript代码运行次数:0运行复制FullHttpResponse httpResponse = channel.readOutbound();
String httpResponseContent = httpResponse.content()
.toString(Charset.defaultCharset());
assertThat(httpResponseContent).isEqualTo("15");
4. 测试异常处理
另一个常见的测试方案是异常处理。
我们可以通过实现 exceptionCaught() 方法来处理 ChannelInboundHandlers 中的异常,但在某些情况下,我们不想处理异常,而是将其传递给管道中的下一个 ChannelHandler。
我们可以使用 EmbeddedChannel类中的 checkException() 方法来检查管道上是否接收到任何可抛掷对象并重新抛出它。
通过这种方式,我们可以捕获异常并检查通道处理程序是否应该抛出它:
代码语言:javascript代码运行次数:0运行复制assertThatThrownBy(() -> {
channel.pipeline().fireChannelRead(wrongHttpRequest);
channel.checkException();
}).isInstanceOf(UnsupportedOperationException.class)
.hasMessage("HTTP method not supported");
我们可以在上面的示例中看到,我们已经发送了一个 HTTP 请求,我们希望该请求会触发异常。通过使用 checkException() 方法,我们可以重新抛出管道中存在的最后一个异常,因此我们可以断言需要从中获取什么。
5. 结论
EmbeddedChannel 是 Netty 框架提供的一项重要功能,可帮助我们测试 ChannelHandler 管道的正确性。它可用于单独测试每个通道处理程序,更重要的是测试整个管道。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2021-08-25,如有侵权请联系 cloudcommunity@tencent 删除嵌入式netty测试异常java发布者:admin,转转请注明出处:http://www.yc00.com/web/1747923048a4705755.html
评论列表(0条)