版权声明:转载随意,附上转载信息即可 :) https://blog.csdn.net/Al_assad/article/details/79472347
Netty 使用 EmbeddedChannel 进行单元测试
对于 Netty 的 ChannelHandler 进行单元测试,Netty 提供了 EmbeddedChannel 嵌入式通道来完成这一过程,主要使用该通道来测试数据的入站出站过程是否合法;
该通道提供以下常用的 API:
writeInbound | 写一个入站消息到 EmbeddedChannel。 如果数据能从 EmbeddedChannel 通过 readInbound() 读到,则返回 true; |
readInbound | 从 EmbeddedChannel 读到入站消息。任何返回遍历整个ChannelPipeline。如果读取还没有准备,则此方法返回 null; |
writeOutbound | 写一个出站消息到 EmbeddedChannel。 如果数据能从 EmbeddedChannel 通过 readOutbound() 读到,则返回 true; |
readOutbound | 从 EmbeddedChannel 读到出站消息。任何返回遍历整个ChannelPipeline。如果读取还没有准备,则此方法返回 null; |
Finish | 如果从入站或者出站中能读到数据,标记 EmbeddedChannel 完成并且返回。这同时会调用 EmbeddedChannel 的关闭方法; |
以下图示了 ChannelPipeline 使用 EmbeddedChannel 的方法:
以下实例完整代码地址:
https://gitee.com/assad/netty-test-sample/tree/master/netty-test-sample/src/main/java/junitSample
入站处理器测试
以下测试一个入站解码器 FixedLengthFrameDecoder;
FixedLengthFrameDecoder
//用于进行测试的 Decoder,将读取的帧分隔为固定长度
public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
private final int frameLength; //帧长度
public FixedLengthFrameDecoder(int frameLength) {
this.frameLength = frameLength;
}
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
//帧分割
while(in.readableBytes() >= frameLength)
out.add(in.readBytes(frameLength));
}
}
测试代码:
public void testFixedFrameDecoder(){
EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(4));
//测试入站写入
ByteBuf buf = Unpooled.buffer();
for(int i = 0; i < 10 ; i++)
buf.writeByte(i);
ByteBuf in = buf.duplicate();
//入站写入3个字节,此时 Decoder 会缓存这些数据,并没有转发这些数据到下一个 ChannelHandler
assertFalse(channel.writeInbound(in.readBytes(3)));
//入站写入7个字节,加上之前写入的3个字节,Decoder 转发其中前8个字节,分为2组转发给下一个 ChannelHandler,剩余2个字节仍被缓存
assertTrue(channel.writeInbound(in.readBytes(7)));
assertTrue(channel.finish()); //向通道发送结束信号
//测试入站读取
//由上面的写入过程可以估计,前2次都可以读取到值,第3次读取为空值
ByteBuf read = channel.readInbound();
assertEquals(read,buf.readSlice(4));
read.release();
read = channel.readInbound();
assertEquals(read,buf.readSlice(4));
read.release();
read = channel.readInbound();
assertNull(read);
}
出站处理器测试
以下测试一个入站编码器
FixedLengthFrameDecoder;
FixedLengthFrameDecoder
// 用于测试的 Encoder,将读取的 Integer 绝对值化
public class AbsIntegerEncoder extends MessageToMessageEncoder<ByteBuf> {
protected void encode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
while(in.readableBytes() >= 4){
int i = Math.abs(in.readInt());
out.add(i);
}
}
}
测试代码:
public void testAbsIntegerEncoder(){
EmbeddedChannel channel = new EmbeddedChannel(new AbsIntegerEncoder());
//测试出站写入
ByteBuf buf = Unpooled.buffer();
for(int i = 0; i < 10; i++)
buf.writeInt(i * -1);
assertTrue(channel.writeOutbound(buf));
assertTrue(channel.finish());
//测试出站读取
for(int i = 0; i < 10; i++)
assertEquals((Integer)i,channel.readOutbound());
assertNull(channel.readOutbound());
}
异常捕获测试
抛出异常的处理器,
FixedLengthFrameDecoder
public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
private final int frameLength; //帧长度
private final int maxFrameSize; //最大帧长度
public FixedLengthFrameDecoder(int frameLength) {
this.frameLength = frameLength;
this.maxFrameSize = 256;
}
public FixedLengthFrameDecoder(int frameLength, int maxFrameSize) {
this.frameLength = frameLength;
this.maxFrameSize = maxFrameSize;
}
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
//过长帧异常
if(in.readableBytes() >= maxFrameSize){
in.clear();
throw new TooLongFrameException();
}
//帧分割
while(in.readableBytes() >= frameLength)
out.add(in.readBytes(frameLength));
}
}
测试代码:
public void testFixedFrameDecoderException(){
EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(4,10));
ByteBuf buf = Unpooled.buffer();
for(int i = 0; i < 30; i++)
buf.writeByte(i);
try{
channel.writeInbound(buf.duplicate());
fail();
}catch(TooLongFrameException e){
e.printStackTrace();
}
}