Netty 使用 EmbeddedChannel 進行單元測試
writeInbound | 寫一個入站消息到 EmbeddedChannel。 如果數據能從 EmbeddedChannel 通過 readInbound() 讀到,則返回 true; |
readInbound | 從 EmbeddedChannel 讀到入站消息。任何返回遍歷整個ChannelPipeline。如果讀取還沒有準備,則此方法返回 null; |
writeOutbound | 寫一個出站消息到 EmbeddedChannel。 如果數據能從 EmbeddedChannel 通過 readOutbound() 讀到,則返回 true; |
readOutbound | 從 EmbeddedChannel 讀到出站消息。任何返回遍歷整個ChannelPipeline。如果讀取還沒有準備,則此方法返回 null; |
Finish | 如果從入站或者出站中能讀到數據,標記 EmbeddedChannel 完成並且返回。這同時會調用 EmbeddedChannel 的關閉方法; |
入站處理器測試
//用於進行測試的 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);
}
出站處理器測試
// 用於測試的 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());
}
異常捕獲測試
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();
}
}