一种特殊的Channel实现----EmbeddedChannel,它是Netty专门为改进针对ChannelHandler的单元测试而提供的。

名称 职责
writeInbound 将入站消息写到EmbeddedChannel中。如果可以通过readInbound方法从EmbeddedChannel中读取数据,则返回true
readInbound 从EmbeddedChannel中读取入站消息。任何返回东西都经过整个ChannelPipeline。如果没有任何可供读取的,则返回null
writeOutbound 将出站消息写到EmbeddedChannel中,如果现在可以通过readOutbound从EmbeddedChannel中读取到东西,则返回true
readOutbound 从EmbeddedChannel中读取出站消息。任何返回东西都经过整个ChannelPipeline。如果没有任何可供读取的,则返回null
finish 将EmbeddedChannel标记为完成,如果有可读取的入站或出站数据,则返回true。这个方法还将会调用EmbeddedChannel上的close方法

测试入站消息

public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
private final int frameLength; public FixedLengthFrameDecoder(int frameLength) {
if (frameLength <= 0) {
throw new IllegalArgumentException("frameLength must be positive integer: " + frameLength);
}
this.frameLength = frameLength;
} @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
while (in.readableBytes() >= frameLength) {
ByteBuf buf = in.readBytes(frameLength);
out.add(buf);
}
}
}
public class FixedLengthFrameDecoderTest {
@Test
public void testFramesDecoded() {
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));
Assert.assertTrue(channel.writeInbound(input.retain()));
Assert.assertTrue(channel.finish()); ByteBuf read = channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release(); read = channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release(); read = channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release(); Assert.assertNull(channel.readInbound());
buf.release();
} @Test
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));
Assert.assertFalse(channel.writeInbound(input.readBytes(2)));
Assert.assertTrue(channel.writeInbound(input.readBytes(7)));
Assert.assertTrue(channel.finish());
ByteBuf read = channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release(); read = channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release(); read = channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release(); Assert.assertNull(channel.readInbound());
buf.release();
}
}

测试出站消息

public class AbsIntegerEncoder extends MessageToMessageEncoder<ByteBuf> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) throws Exception {
while (in.readableBytes() >= 4) {
int value = Math.abs(in.readInt());
out.add(value);
}
}
}
public class AbsIntegerEncoderTest {
@Test
public void testEncoded() {
ByteBuf buf = Unpooled.buffer();
for (int i = 0; i < 10; i++) {
buf.writeInt(i * -1);
}
EmbeddedChannel channel = new EmbeddedChannel(new AbsIntegerEncoder());
Assert.assertTrue(channel.writeOutbound(buf));
Assert.assertTrue(channel.finish()); for (int i = 0; i < 10; i++) {
Assert.assertEquals(Integer.valueOf(i), channel.readOutbound());
}
Assert.assertNull(channel.readOutbound());
}
}

测试异常处理

public class FrameChunkDecoder extends ByteToMessageDecoder {
private final int maxFrameSize; public FrameChunkDecoder(int maxFrameSize) {
this.maxFrameSize = maxFrameSize;
} @Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
int readableBytes = in.readableBytes();
if (readableBytes > maxFrameSize) {
in.clear();
throw new TooLongFrameException();
}
ByteBuf buf = in.readBytes(readableBytes);
out.add(buf);
}
}
public class FrameChunkDecoderTest {
@Test
public void testFramesDecoded() {
ByteBuf buf = Unpooled.buffer();
for (int i = 0; i < 9; i++) {
buf.writeByte(i);
}
ByteBuf input = buf.duplicate();
EmbeddedChannel channel = new EmbeddedChannel(new FrameChunkDecoder(3));
Assert.assertTrue(channel.writeInbound(input.readBytes(2)));
try {
channel.writeInbound(input.readBytes(4));
Assert.fail();
} catch (TooLongFrameException e) { }
Assert.assertTrue(channel.writeInbound(input.readBytes(3)));
Assert.assertTrue(channel.finish()); ByteBuf read = channel.readInbound();
Assert.assertEquals(buf.readSlice(2), read);
read.release(); read = channel.readInbound();
Assert.assertEquals(buf.skipBytes(4).readSlice(3), read);
read.release();
buf.release();
}
}

netty使用EmbeddedChannel对channel的出入站进行单元测试的更多相关文章

  1. 自顶向下深入分析Netty(六)--Channel总述

    自顶向下深入分析Netty(六)--Channel总述 自顶向下深入分析Netty(六)--Channel源码实现 6.1 总述 6.1.1 Channel JDK中的Channel是通讯的载体,而N ...

  2. Netty那点事: 概述, Netty中的buffer, Channel与Pipeline

    Netty那点事(一)概述 Netty和Mina是Java世界非常知名的通讯框架.它们都出自同一个作者,Mina诞生略早,属于Apache基金会,而Netty开始在Jboss名下,后来出来自立门户ne ...

  3. netty做集群 channel共享 方案

    netty做集群 channel如何共享? 方案一: netty 集群,通过rocketmq等MQ 推送到所有netty服务端, channel 共享无非是要那个通道都可以发送消息向客户端, MQ广播 ...

  4. Netty源码分析之ChannelPipeline—入站事件的传播

    之前的文章中我们说过ChannelPipeline作为Netty中的数据管道,负责传递Channel中消息的事件传播,事件的传播分为入站和出站两个方向,分别通知ChannelInboundHandle ...

  5. Netty源码分析之ChannelPipeline—出站事件的传播

    上篇文章中我们梳理了ChannelPipeline中入站事件的传播,这篇文章中我们看下出站事件的传播,也就是ChannelOutboundHandler接口的实现. 1.出站事件的传播示例 我们对上篇 ...

  6. Netty源码分析--Channel注册(上)(五)

    其实在将这一节之前,我们来分析一个东西,方便下面的工作好开展. 打开启动类,最开始的时候创建了一个NioEventLoopGroup 事件循环组,我们来跟一下这个. 这里bossGroup, 我传入了 ...

  7. Netty源码分析--Channel注册(中)(六)

    接上一篇,我们继续看 不知道大家第一次看这段代码的时候有没有一脸懵逼,反正我是一脸懵,为什么这个if else 最终都是调用的register0方法,都是一样的. 其实这里就是为什么Netty是线程安 ...

  8. 003——Netty之Buffer、Channel以及多路复用器Selector

    Buffer 1.缓冲区类型 2.缓冲区定义 (1)Buffer是一个对象,其中包含写入与读出的数据.是新IO与原IO的重要区别.任何情况下访问NIO中的数据都需要通过缓存区进行操作. (2)Buff ...

  9. netty(五) channel

    问题 channel 是如何处理发送一半中断后继续重发的 channel 具体作用是什么 概述 这一节我们将介绍 Channel 和内部接口 Unsafe .其中Unsafe 是内部接口,聚合在Cha ...

随机推荐

  1. 【面试】MySQL 中NULL和空值的区别?

    做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 01 小木的故事 作为后台开发,在日常工作中如果要接触Mysql数据库,那么不可避免会遇到Mysql中的NULL和空值.那 ...

  2. Linux下编译PHP常见错误及解决方法

    1.configure: error: xml2-config not found. Please check your libxml2 installation.yum install libxml ...

  3. kuberbetes基础概念

    部署了一大堆,来了解一下K8S一些基本的概念. 1.Node Node作为集群中的工作节点,运行真正的应用程序,在Node上Kubernetes管理的最小运行单元是Pod.Node上运行着Kubern ...

  4. 消息驱动式微服务:Spring Cloud Stream & RabbitMQ

    1. 概述 在本文中,我们将向您介绍Spring Cloud Stream,这是一个用于构建消息驱动的微服务应用程序的框架,这些应用程序由一个常见的消息传递代理(如RabbitMQ.Apache Ka ...

  5. Java基础中字符串与字符的注意点!

    在Java中,字符的表达与字符串的表达是不一样的!话不多说,直接上代码!!! String  a="a"; char a='a'; 其中他们的引号是不一样的

  6. python的输入和输出

    基本输出 python中的输出使用关键字--print,与python2不同的是,python3的输出后面必须要加括号,示例如下: python3.0以上输出: python2.0以上的输出: 格式化 ...

  7. Python之matplotlib库学习:实现数据可视化

    1. 安装和文档 pip install matplotlib 官方文档 为了方便显示图像,还使用了ipython qtconsole方便显示.具体怎么弄网上搜一下就很多教程了. pyplot模块是提 ...

  8. HDU 3061:Battle(最大权闭合图)

    http://acm.hdu.edu.cn/showproblem.php?pid=3061 题意:中文题意. 思路:和上一题神似啊,比上一题还简单,重新看了遍论文让我对这个理解更加深了. 闭合图:如 ...

  9. linux上mysql MM(双主)架构及keepalived搭建

    master1 10.1.1.14 VIP 10.1.1.16master2 10.1.1.15 VIP 10.1.1.16 一.mysql MM配置1.修改master1的my.cnf# vi /e ...

  10. find文件删除

    find /root/title/test -type f -name '*.txt' -exec rm {} \;   查找并删除test文件夹下所有txt文件 find /root/title/t ...