Netty Unit Test

Netty 단위 테스트 간단 정리.

ChannelHandler를 단위 테스트 하기 위해서 EmbeddedChannel을 이용한다.
import io.netty.channel.embedded.EmbeddedChannel;

EmbeddedChannel 주요 API

1. writeInboud(Object... msgs)
  -> EmbeddedChannel inbound에 msgs를 쓴다.
      readInbound()로 읽어 올 수 있는 상태(=next handler에게 event 전파)이면 true리턴. 

2. readInboud()
  -> EmbeddedChannel inbound 메세지를 읽는다.
      writeInboud()로 pipeline을 거쳐 저장된 결과를 리턴 하고 값이 없으면 null 리턴.

3. writeOutbound(Object... msgs)
  -> EmbeddedChannel outbound에 msgs를 쓴다.
      readOutbound()로 읽어 올 수 있는 상태(=next handler에게 event 전파)이면 true 리턴.

4. readOutbound()
  -> EmbeddedChannel outbound 메세지를 읽는다.
      writeOutbound()로 pipeline을 거쳐 저장된 결과를 리턴 하고 값이 없으면 null 리턴.

5. finish()
  -> EmbeddedChannel이 완료 되었음을 표시.
      inbound 또는 outbound 데이터를 읽을 수 있으면 true 리턴.
      EmbeddedChannel.close() 도 호출.


출처: Netty in Action


Unit Test 예제

1. netty pom.xml
1
2
3
4
5
<dependency>
    <groupId>io.netty</groupId>
    <artifactId>netty-all</artifactId>
    <version>4.1.65.Final</version>
</dependency>

2. 테스트 용으로 int 값을 받아서 x2 결과 값을 주는 ChannelHandler 구현
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
public class MyChannelHandler extends SimpleChannelInboundHandler<ByteBuf> {
    private ByteBuf intact;

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        intact = ctx.alloc().buffer(4);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        intact.release();
        intact = null;
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf in) throws Exception {
        intact.writeBytes(in);
        if (intact.readableBytes() >= 4) {
            int msg = intact.readInt();
            msg *= 2;
            ctx.fireChannelRead(Unpooled.buffer(4).writeInt(msg));
        }
    }
}

3. 단위 테스트 코드
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class MyChannelHandlerTest {
    @Test
    void test_MyChannelHandler() {
        int inData = 1234;
        byte[] inDataBytes = Unpooled.buffer(4).writeInt(inData).array();

        byte[] inDataFrame1 = new byte[2];
        byte[] inDataFrame2 = new byte[2];

        inDataFrame1[0] = inDataBytes[0];
        inDataFrame1[1] = inDataBytes[1];
        inDataFrame2[0] = inDataBytes[2];
        inDataFrame2[1] = inDataBytes[3];

        EmbeddedChannel channel = new EmbeddedChannel(new MyChannelHandler());

        // write to inbound
        assertFalse(channel.writeInbound(Unpooled.buffer(2).writeBytes(inDataFrame1)));
        assertTrue(channel.writeInbound(Unpooled.buffer(2).writeBytes(inDataFrame2)));
        assertTrue(channel.finish());

        // read inbound
        ByteBuf out = channel.readInbound();
        assertEquals(out.readInt(), inData * 2);

        out.release();
    }
}

note) MyChannelHandler에서 4byte가 모아지길 기다렸다가 수행되는 것도 테스트 해 보기 위해 일부러 2byte 씩 나눠서 입력 값을 주었다.


댓글

이 블로그의 인기 게시물

[Protocol] WIEGAND 통신

Orange for Oracle에서 한글 깨짐 해결책

[UI] GNB·LNB·SNB·FNB 용어 설명