Netty学习摘记 —— 单元测试

本文参考

本篇文章是对《Netty In Action》一书第九章"单元测试"的学习摘记,主要内容为使用特殊的 Channel 实现——EmbeddedChannel来测试ChannelHandler

EmbeddedChannel概述

将入站数据或者出站数据写入到 EmbeddedChannel 中,然后检查是否有任何东西到达了 ChannelPipeline 的尾端。以这种方式,你便可以确定消息是否已经被编码或者被解码过了,以及是否触发了任何的ChannelHandler动作

从上表的API描述中我们可以看到,writeInbound()和readInbound()方法、writeOutbound()和readOutbound()方法成对使用,他们的流程是十分简单的

 

使用EmbeddedChannel测试入站消息

我们设计一个解码器,每次读取固定字节大小的帧

public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
private final int frameLength;

//
指定要生成的帧的长度
public FixedLengthFrameDecoder(int frameLength) {
if (frameLength <= 0) {
throw new IllegalArgumentException(
"frameLength must be a positive integer: " + frameLength);
}
this.frameLength = frameLength;
}

@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out)
throws Exception {
//
检查是否有足够的字节可以被读取,以生成下一个帧
while (in.readableBytes() >= frameLength) {
//
ByteBuf 中读取一个新帧
ByteBuf buf = in.readBytes(frameLength);
//
将该帧添加到已被解码的消息列表中
out.add(buf);
}
}
}

使用EmbeddedChannel对解码器进行单元测试

@Test
//
第一个测试方法:testFramesDecoded()
public void
testFramesDecoded() {
//
创建一个 ByteBuf,并存储 9 字节
ByteBuf buf = Unpooled.buffer();
for (int i = 0; i < 9; i++) {
buf.writeByte(i);
}
ByteBuf input = buf.duplicate();
//
创建一个EmbeddedChannel,并添加一个FixedLengthFrameDecoder
//其将以 3 字节的帧长度被测试
EmbeddedChannel channel = new EmbeddedChannel(
new FixedLengthFrameDecoder(3));
// write bytes
//
将数据写入EmbeddedChannel
assertTrue
(channel.writeInbound(input.retain()));
//
标记 Channel 为已完成状态
assertTrue(channel.finish());

// read messages
//
读取所生成的消息,并且验证是否有 3 帧(切片),其中每帧(切片)都为 3 字节
ByteBuf read = (ByteBuf) channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();

read = (ByteBuf) channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();

read = (ByteBuf) channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();

assertNull(channel.readInbound());
buf.release();
}

该 testFramesDecoded()方法验证了,一个包含 9 个可读字节的 ByteBuf 被解码为 3 个ByteBuf,每个都包含了 3 字节,,通过调用readInbound()方法,从Embedded- Channel中正好读取了3 个帧和一个null

下面测试入站ByteBuf通过两个步骤来写入

@Test
//
第二个测试方法:testFramesDecoded2()
public void
testFramesDecoded2() {
ByteBuf buf = Unpooled.buffer();
for (int i = 0; i < 9; i++) {
buf.writeByte(i);
}
ByteBuf input = buf.duplicate();

EmbeddedChannel channel = new EmbeddedChannel(
new FixedLengthFrameDecoder(3));
//
返回 false,因为没有一个完整的可供读取的帧
assertFalse(channel.writeInbound(input.readBytes(2)));
assertTrue(channel.writeInbound(input.readBytes(7)));
assertTrue(channel.finish());

ByteBuf read = (ByteBuf) channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();

read = (ByteBuf) channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();

read = (ByteBuf) channel.readInbound();
assertEquals(buf.readSlice(3), read);
read.release();

assertNull(channel.readInbound());
buf.release();
}

当writeInbound(input.readBytes(2))被调用时,返回了false,这也应证了前面API表中的描述,如果对 readInbound()的后续调用将会返回数据,那么 write- Inbound()方法将会返回true,或者用源码的注释来说,当只有不足3个字节可供读取时,没有生成新的帧添加到已被解码的消息队列中

return true if the write operation did add something to the inbound buffer

 

使用EmbeddedChannel测试出站消息

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

猜你喜欢

转载自www.cnblogs.com/kuluo/p/12666050.html
今日推荐