java: unit test lambda expression inside dispatcher

亡梦爱人 提交于 2019-12-11 16:31:15

问题


I have a class:

public class RequestHandler implements HttpHandler {
  public void handleRequest(HttpServerExchange serverContext) throws Exception {
    serverContext.dispatch(() -> serverContext.getRequestReceiver()
        .receiveFullBytes((httpServerExchange, reqBytes) -> {

          // business logic along with few function call

        }
      )
    );

  }
} 

I want to write a unit test case to test my business logic. I am not sure how to do it with 2 levels of a lambda expression insider a dispatcher? Can someone please suggest a good way to write test cases?

I know that we can move business logic to new class and can test it (i guess it's better designed) but curious to know what if it's part of some legacy code or something that we can't change, how can we test it?


回答1:


Under the assumption that somewhere in your buisness logic you forward the received message (or whatever you do with it) to somewhere else, you can just test your code as usual.

Note that HttpServerExchange is a final class, so you need to use a Mockito version that supports final mocking - and you have to enable it, as described here.

To get around the lambda expression you need to use thenAnswer or doAnswer to trigger the invocation of the correct interface method manually.

A simple example could look like this:

import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.stubbing.Answer;

import io.undertow.io.Receiver;
import io.undertow.io.Receiver.FullBytesCallback;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;

@ExtendWith(MockitoExtension.class)
public class RequestHandlerTest {

    static class BuisnessLogic {
        public void someMethod(HttpServerExchange httpServerExchange, byte[] reqBytes) {
        }
    }

    static class RequestHandler implements HttpHandler {

        BuisnessLogic logic;

        public void handleRequest(HttpServerExchange serverContext) throws Exception {
            serverContext.dispatch(
                () -> serverContext.getRequestReceiver().receiveFullBytes(
                    (httpServerExchange, reqBytes) -> {
                        logic.someMethod(httpServerExchange, reqBytes);
                    }
                )
            );
        }
    }

    @Mock
    BuisnessLogic logic;

    @InjectMocks
    RequestHandler handler;

    @Test
    public void test() throws Exception {

        byte[] message = new byte[] {1,2,3};
        HttpServerExchange serverContext = Mockito.mock(HttpServerExchange.class);

        // 1st lambda
        Mockito.when(serverContext.dispatch(Mockito.any(Runnable.class)))
               .thenAnswer((Answer<HttpServerExchange>) invocation -> {

            Runnable runnable = invocation.getArgument(0);
            runnable.run();

            return serverContext;
        });

        // 2nd lambda
        Receiver receiver = Mockito.mock(Receiver.class);
        Mockito.doAnswer((Answer<Void>) invocation -> {

            FullBytesCallback callback = invocation.getArgument(0);
            callback.handle(serverContext, message);

            return null;

        }).when(receiver).receiveFullBytes(Mockito.any(FullBytesCallback.class));

        Mockito.when(serverContext.getRequestReceiver()).thenReturn(receiver);

        // class under test - method invocation
        handler.handleRequest(serverContext);

        // buisness logic call verification
        ArgumentCaptor<HttpServerExchange> captor1 = ArgumentCaptor.forClass(HttpServerExchange.class);
        ArgumentCaptor<byte[]> captor2 = ArgumentCaptor.forClass(byte[].class);

        Mockito.verify(logic).someMethod(captor1.capture(), captor2.capture());

        Assertions.assertEquals(serverContext, captor1.getValue());
        Assertions.assertEquals(message, captor2.getValue());
    }
}

As others already mentioned you should only use that approach for legacy code.

A simple refactoring could just push the entire part you need to test into its own method, which - in the example above - would just be the buisness logic itself.

There is no explicit need to test the undertow framework yourself.



来源:https://stackoverflow.com/questions/58077230/java-unit-test-lambda-expression-inside-dispatcher

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!