Исходя из предположения, что где-то в вашей бизнес-логике вы пересылаете полученное сообщение (или что бы вы ни делали с ним) куда-то еще, вы можете просто протестировать свой код как обычно.
Обратите внимание, что HttpServerExchange
- этопоследний класс, поэтому вам нужно использовать версию Mockito, которая поддерживает final
mocking - и вы должны включить ее, как описано here
.
Чтобы обойти лямбда-выражениевам нужно использовать thenAnswer
или doAnswer
для ручного вызова правильного метода интерфейса.
Простой пример может выглядеть следующим образом:
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());
}
}
Как уже упоминалось, вы должны использовать этот подход только для устаревшего кода.
Простой рефакторинг может просто подтолкнуть всю деталь, которую нужно протестировать, к своему собственному методу, который - в приведенном выше примере - будет просто самой логикой бизнеса.
Нет явной необходимости тестировать фреймворк undertow
самостоятельно.