最佳实践要求你的测试不仅要能够证明你的实现是正确的,而且容易隔离那些因修改代码而突然出现的问题。这种类型的测试叫做单元测试。
EmbeddedChannel是netty专门改进针对ChannelHandler的单元测试而提供的。
核心方法:
数据流:
测试入站消息
测试1是直接写入9个字节,被拆分成3个桢,
测试2是分2次写入,第一次2个字节,第二次7个字节,结果和测试1一样。
finish方法将EmbeddedChannel标记为已完成状态。
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)
);
assertTrue(channel.writeInbound(input.retain()));
assertTrue(channel.finish());
//读取消息
ByteBuf read=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();
}
@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));
assertFalse(channel.writeInbound(input.readBytes(2)));
assertTrue(channel.writeInbound(input.readBytes(7)));
assertTrue(channel.finish());
ByteBuf read = (ByteBuf) channel.readInbound();
ByteBuf b2=buf.readSlice(3);
assertEquals(b2, 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();
}
}
解码器:
public class FixedLengthFrameDecoder extends ByteToMessageDecoder {
private final int frameLength;
public FixedLengthFrameDecoder(int frameLength) {
this.frameLength = frameLength;
}
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
while (byteBuf.readableBytes()>=frameLength){
ByteBuf buffer=byteBuf.readBytes(frameLength);
list.add(buffer);
}
}
}
测试出站消息
示例按照下列方式工作:
- 持有AbsIntegerEncoder的EmbeddedChannel以4字节的负整数形式写出站数据。
- 编码器将从传入的ByteBuf中读取每个负整数,并调用Math.abs方法获取绝对值
- 编码器将每个负整数的绝对值写到ChannelPipeline中
编码器:
public class AbsIntegerEncoder extends MessageToMessageEncoder<ByteBuf> {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
while (byteBuf.readableBytes()>=4){
int value=Math.abs(byteBuf.readInt());
list.add(value);
}
}
}
测试用例:
public class AbsIntegerEncoderTest {
@Test
public void testEncoded(){
ByteBuf buf= Unpooled.buffer();
for (int i=1;i<10;i++){
buf.writeInt(i*-1);
}
EmbeddedChannel embeddedChannel=new EmbeddedChannel(
new AbsIntegerEncoder()
);
Assert.assertTrue(embeddedChannel.writeOutbound(buf));
Assert.assertTrue(embeddedChannel.finish());
for (int i=1;i<10;i++){
int a= embeddedChannel.readOutbound();
assertEquals(i,a);
}
assertNull(embeddedChannel.readOutbound());
}
}