3. EmbeddedChannelOverview

The EmbeddedChannelclass is just another implementation of AbstractChannel – which transports data without the need for a real network connection.

This is useful because we can simulate incoming messages by writing data on the inbound channels and also check the generated response on the outbound channels. This way we can individually test each ChannelHandler or in the whole channel pipeline.

To test one or more ChannelHandlers,we first have to create an EmbeddedChannel instance using one of its constructors.

The most common way to initialize an EmbeddedChannel is by passing the list of ChannelHandlers to its constructor:

EmbeddedChannel channel = new EmbeddedChannel(
new HttpMessageHandler(), new CalculatorOperationHandler());

If we want to have more control on the order the handlers are inserted into the pipeline we can create an EmbeddedChannel with the default constructor and directly add the handlers:

The EmbeddedChannel includes methods that we can use to read and write data to our ChannelPipeline. The most commonly used methods are:

readInbound()

readOutbound()

writeInbound(Object… msgs)

writeOutbound(Object… msgs)

The read methods retrieve and remove the first element in the inbound/outbound queue.When we need access to the whole queue of messages without removing any element, we can use the outboundMessages() method:

We can see that we’ve sent the HTTP request on the inbound pipeline using the writeInbound() method and read the result with readInbound(); inboundChannelResponse is the message that resulted from the data we’ve sent after it was processed by all the ChannelHandlers in the inbound pipeline.

Now, let’s check if our Netty server responds with the correct HTTP response message. To do this, we’ll check if a message exists on the outbound pipeline:

assertThat(channel.outboundMessages().size()).isEqualTo(1);

The outbound message, in this case, is an HTTP response, so let’s check if the content is correct. We do this, by reading the last message in the outbound pipeline:

4. Testing Exception Handling

Another common testing scenario is exception handling.

We can handle exceptions in our ChannelInboundHandlers by implementing the exceptionCaught() method, but there’re some cases when we don’t want to handle an exception and instead, we pass it to the next ChannelHandlerin the pipeline.

We can use the checkException() method from the EmbeddedChannelclass to check if any Throwable object was received on the pipeline and rethrows it.

This way we can catch the Exception and check whether the ChannelHandlershould or shouldn’t have thrown it:

We can see in the example above, that we’ve sent an HTTP request that we expect to trigger an Exception. By using the checkException() method we can rethrow the last exception that exists in the pipeline, so we can assert what is needed from it.

5. Conclusion

The EmbeddedChannel is a great feature provided by the Netty framework to help us test the correctness of out ChannelHandler pipeline. It can be used to test each ChannelHandler individually and more importantly the whole pipeline.