W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
本節(jié)的內(nèi)容是介紹Netty中要如何通過 EmbeddedChannel 對 ChannelHandler 進(jìn)行測試。
我們先來編寫一個簡單的 ByteToMessageDecoder 實現(xiàn),在有足夠的數(shù)據(jù)可以讀取的情況下將產(chǎn)生固定大小的包,如果沒有足夠的數(shù)據(jù)可以讀取,則會等待下一個數(shù)據(jù)塊并再次檢查是否可以產(chǎn)生一個完整包。
如圖所示,它可能會占用一個以上的“event”以獲取足夠的字節(jié)產(chǎn)生一個數(shù)據(jù)包,并將它傳遞到 ChannelPipeline 中的下一個 ChannelHandler,
Figure 10.2 Decoding via FixedLengthFrameDecoder
實現(xiàn)如下:
Listing 10.1 FixedLengthFrameDecoder implementation
public class FixedLengthFrameDecoder extends ByteToMessageDecoder { //1
private final int frameLength;
public FixedLengthFrameDecoder(int frameLength) { //2
if (frameLength <= 0) {
throw new IllegalArgumentException(
"frameLength must be a positive integer: " + frameLength);
}
this.frameLength = frameLength;
}
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
if (in.readableBytes() >= frameLength) { //3
ByteBuf buf = in.readBytes(frameLength);//4
out.add(buf); //5
}
}
}
下面是單元測試的例子,使用 EmbeddedChannel
Listing 10.2 Test the FixedLengthFrameDecoder
public class FixedLengthFrameDecoderTest {
@Test //1
public void testFramesDecoded() {
ByteBuf buf = Unpooled.buffer(); //2
for (int i = 0; i < 9; i++) {
buf.writeByte(i);
}
ByteBuf input = buf.duplicate();
EmbeddedChannel channel = new EmbeddedChannel(new FixedLengthFrameDecoder(3)); //3
Assert.assertFalse(channel.writeInbound(input.readBytes(2))); //4
Assert.assertTrue(channel.writeInbound(input.readBytes(7)));
Assert.assertTrue(channel.finish()); //5
ByteBuf read = (ByteBuf) channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release();
read = (ByteBuf) channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release();
read = (ByteBuf) 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 = (ByteBuf) channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release();
read = (ByteBuf) channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release();
read = (ByteBuf) channel.readInbound();
Assert.assertEquals(buf.readSlice(3), read);
read.release();
Assert.assertNull(channel.readInbound());
buf.release();
}
}
如上面代碼,testFramesDecoded() 方法想測試一個 ByteBuf,這個ByteBuf 包含9個可讀字節(jié),被解碼成包含了3個可讀字節(jié)的 ByteBuf。你可能注意到,它寫入9字節(jié)到通道是通過調(diào)用 writeInbound() 方法,之后再執(zhí)行 finish() 來將 EmbeddedChannel 標(biāo)記為已完成,最后調(diào)用readInbound() 方法來獲取 EmbeddedChannel 中的數(shù)據(jù),直到?jīng)]有可讀字節(jié)。testFramesDecoded2() 方法采取同樣的方式,但有一個區(qū)別就是入站ByteBuf分兩步寫的,當(dāng)調(diào)用 writeInbound(input.readBytes(2)) 后返回 false 時,F(xiàn)ixedLengthFrameDecoder 值會產(chǎn)生輸出,至少有3個字節(jié)是可讀,testFramesDecoded2() 測試的工作相當(dāng)于testFramesDecoded()。
測試的處理出站消息類似于我們剛才看到的一切。這個例子將使用的實現(xiàn)MessageToMessageEncoder:AbsIntegerEncoder。
圖10.3顯示了邏輯。
Figure 10.3 Encoding via AbsIntegerEncoder
示例如下:
Listing 10.3 AbsIntegerEncoder
public class AbsIntegerEncoder extends MessageToMessageEncoder<ByteBuf> { //1
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, ByteBuf in, List<Object> out) throws Exception {
while (in.readableBytes() >= 4) { //2
int value = Math.abs(in.readInt());//3
out.add(value); //4
}
}
}
在前面的示例中,我們將使用 EmbeddedChannel 測試代碼。清單10.4
Listing 10.4 Test the AbsIntegerEncoder
public class AbsIntegerEncoderTest {
@Test //1
public void testEncoded() {
ByteBuf buf = Unpooled.buffer(); //2
for (int i = 1; i < 10; i++) {
buf.writeInt(i * -1);
}
EmbeddedChannel channel = new EmbeddedChannel(new AbsIntegerEncoder()); //3
Assert.assertTrue(channel.writeOutbound(buf)); //4
Assert.assertTrue(channel.finish()); //5
for (int i = 1; i < 10; i++) {
Assert.assertEquals(i, channel.readOutbound()); //6
}
Assert.assertNull(channel.readOutbound());
}
}
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: