Dean Hiller
Dean Hiller

Reputation: 20204

How to mock Netty?

I just inherited a project using netty and it seems to entangle itself in the code in that many handlers are created implementing netty interfaces, etc. I want to mock it in such a way that I can add tests to test from the netty api upwards, firing bytes in and receiving bytes back but not connecting a socket to do so. Is there any way to fire into the pipeline myself which would test netty code as well as our code and also receive from the code?

Specifically, I am looking to do something like this:

SysUnderTest(channel) {
  channel.addReadListener(myListenerImpl);
}

Test {
   testStuff() {
       channelMock = new MockChannel(); 
       SysUnderTest system = new SysUnderTest(channelMock);
       //BIG NOTE: The get here is just getting what the mocked cached when the SysUnderTest
       //ended up calling the channel.addReadLsitener(listenerImpl)!!!
       ReadListener listenerImplToTest = channelMock.getAddedListenerImpl();
       listenerImplToTest.fireNewDataIncoming(byteBuffer1);
       Assert.Equals("new state", system.getState());
       listenerImplToTest.fireNewDataIncoming(byteBuffer2);
       Assert.Equals("state2", system.getState());
   }
}

Maybe I need a paradigm shift but I think any system testing with an IO library should be firing data to a listener that will react. My test needs to fire data in by invoking the listener implementation's event method (and it gets the listenerImpl though the mock channel), but I don't see how to do this in netty. Specifically, which method is firing data in for the example above. It looks like it's reading the data (which seems more like a blocking/polling thing). Maybe I need to change my paradigm of the way I am thinking about this though?

Upvotes: 0

Views: 3697

Answers (2)

Veebs
Veebs

Reputation: 2388

You can try using mock objects.

See https://github.com/netty/netty/pull/119.

 @Test
 public void testPerformOpeningHandshake() {
     Channel channelMock = EasyMock.createMock(Channel.class);

     DefaultChannelPipeline pipeline = createPipeline();

     EasyMock.expect(channelMock.getPipeline()).andReturn(pipeline);

     // capture the http response in order to verify the headers
     Capture<HttpResponse> res = new Capture<HttpResponse>();
     EasyMock.expect(channelMock.write(capture(res))).andReturn(new DefaultChannelFuture(channelMock, true));

     replay(channelMock);

     HttpRequest req = new DefaultHttpRequest(HTTP_1_1, HttpMethod.GET, "/chat");
     req.setHeader(Names.HOST, "server.example.com");
     req.setHeader(Names.UPGRADE, WEBSOCKET.toLowerCase());
     req.setHeader(Names.CONNECTION, "Upgrade");
     req.setHeader(Names.SEC_WEBSOCKET_KEY, "dGhlIHNhbXBsZSBub25jZQ==");
     req.setHeader(Names.SEC_WEBSOCKET_ORIGIN, "http://example.com");
     req.setHeader(Names.SEC_WEBSOCKET_PROTOCOL, "chat, superchat");
     req.setHeader(Names.SEC_WEBSOCKET_VERSION, "13");

     WebSocketServerHandshaker17 handsaker17 = new WebSocketServerHandshaker17("ws://example.com/chat", "chat", false);
     handsaker17.performOpeningHandshake(channelMock, req);

     Assert.assertEquals("s3pPLMBiTxaQ9kYGzzhZRbK xOo=", res.getValue().getHeader(Names.SEC_WEBSOCKET_ACCEPT));
     Assert.assertEquals("chat", res.getValue().getHeader(Names.SEC_WEBSOCKET_PROTOCOL));
 }

Upvotes: 0

forty-two
forty-two

Reputation: 12817

Yes, have a look at the embedder package in the javadoc, Especially the DecoderEmbedder class.

Upvotes: 4

Related Questions