netty基础09_利用EmbeddedChannel做单元测试

时间:2020-05-29
本文章向大家介绍netty基础09_利用EmbeddedChannel做单元测试,主要包括netty基础09_利用EmbeddedChannel做单元测试使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
netty提供了一种特殊的Channel 实现——EmbeddedChannel用来测试ChannelHandler;
例如:想测试自己编写服务端解码器是否能正确解码;
想在程序中测试需要在客户端给服务端发送消息,不方便调试;
使用EmbeddedChannel可以做到本地调试解码器;
1.EmbeddedChannel的api
2.运行机制
可以在EmbeddedChannel的有参构造中添加ChannelHandler;
EmbeddedChannel channel = new EmbeddedChannel(new MyDecoder());
对于入站消息:
    调用EmbeddedChannel的writeInbound方法将数据写入管道;
    数据会被管道中的入站处理器处理;
    然后可以调用readInbound方法的到处理后的数据,看处理后的数据是否符合预期;
对于出站消息:
    和入站消息的处理方法类似,只不过调用的方法不同;
    调用writeOutbound方法,将出站的数据写入管道;
    数据会被管道中的出站处理器处理;
    调用readOutbound方法可以得到处理后的数据,看是否被正确处理;
3.测试
工具类HexUtil:用来将字节数组转换成十六进制字符串;
public class HexUtil {
    private static final char[] DIGITS_UPPER = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D',
          'E', 'F' };
 
    public static byte[] decode(char[] data) {
       int len = data.length;
       if ((len & 0x01) != 0) {
          throw new IllegalArgumentException("Odd number of characters.");
       }
       byte[] out = new byte[len >> 1];
       // two characters form the hex value.
       for (int i = 0, j = 0; j < len; i++) {
          int f = toDigit(data[j], j) << 4;
          j++;
          f = f | toDigit(data[j], j);
          j++;
          out[i] = (byte) (f & 0xFF);
       }
       return out;
    }
 
    public static char[] encode(byte[] data) {
       return encode(data, DIGITS_UPPER);
    }
 
    private static char[] encode(byte[] data, char[] toDigits) {
       int l = data.length;
       char[] out = new char[l << 1];
       // two characters form the hex value.
       for (int i = 0, j = 0; i < l; i++) {
          out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
          out[j++] = toDigits[0x0F & data[i]];
       }
       return out;
    }
 
    public static String encodeString(byte[] data) {
       return new String(encode(data));
    }
 
    private static int toDigit(char ch, int index) {
       final int digit = Character.digit(ch, 16);
       if (digit == -1) {
          throw new IllegalArgumentException("Illegal hexadecimal character " + ch + " at index " + index);
       }
       return digit;
    }
}
1)入站消息测试
目的:解码器会将字节数组解码成一帧4个字节的消息,看是否正确解码;
解码器:
public class MyDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
        if(byteBuf.readableBytes() >= 4){
            ByteBuf buf = byteBuf.readBytes(4);    //从消息中读取4个字节,并放到消息列表
            list.add(buf);
        }
    }
}
测试类:可以用Junit来测试
@Test
public void testInBound() throws Exception{
    ByteBuf buf = Unpooled.buffer();
    for(int i=0;i<6;i++){
        buf.writeByte(i);
    }
    ByteBuf buf2 = Unpooled.buffer();
    for(int i=0;i<10;i++){
        buf2.writeByte(i+6);
    }
    EmbeddedChannel channel = new EmbeddedChannel(new MyDecoder());    //新建EmbeddedChannel对象用来测试解码器,构造方法中添加待测解码器实例
    channel.writeInbound(buf);
    channel.writeInbound(buf2);
    channel.finish();    //总共将16个字节的数据写入到进站消息中
 
    ByteBuf read = channel.readInbound();    //获取一条解码后数据,如果正确解码应该是前4个字节的数据;
    System.out.println(HexUtil.encodeString(ByteBufUtil.getBytes(read)));
 
    read.release();
    read = channel.readInbound();        //再次获取解码后的数据,如果正确解码,应该是得到第5~8字节的数据
    System.out.println(HexUtil.encodeString(ByteBufUtil.getBytes(read)));
 
    read.release();
    read = channel.readInbound();    //9~12字节
    System.out.println(HexUtil.encodeString(ByteBufUtil.getBytes(read)));
 
    read.release();
    read = channel.readInbound();    //13~16字节
    System.out.println(HexUtil.encodeString(ByteBufUtil.getBytes(read)));
 
}
结果:可以看到4次获取解码后的消息,每次得到4个字节的数据,说明解码符合预期;
2)出站消息测试
编码器:继承自消息转消息编码器,将ByteBuf转为字符串
public class MyEncoder extends MessageToMessageEncoder<ByteBuf>{
 
    @Override
    protected void encode(ChannelHandlerContext context, ByteBuf buf, List<Object> list) throws Exception {
        int size = buf.readableBytes();
        while(buf.readableBytes() >= 4){
            String hex = HexUtil.encodeString(ByteBufUtil.getBytes(buf.readBytes(4)));    //每4个字节转换成一个字符串,存入出队消息列表中
            list.add(hex);
        }
    }
}
测试类:16个字节用编码器做消息转换,每4个字节转成一个字符串
@Test
public void testOutBound(){
    ByteBuf buf = Unpooled.buffer();
    for(int i=0;i<16;i++){
        buf.writeByte(i);
    }
 
    EmbeddedChannel channel = new EmbeddedChannel(new MyEncoder());
    channel.writeOutbound(buf);
    channel.finish();
 
    System.out.println((String)channel.readOutbound());
    System.out.println((String)channel.readOutbound());
    System.out.println((String)channel.readOutbound());
    System.out.println((String)channel.readOutbound());
}
结果:将16字节的ByteBuf转换成了4个字符串

原文地址:https://www.cnblogs.com/ShiningArmor/p/12988444.html