package org.mockserver.proxy;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockserver.client.netty.NettyHttpClient;
import org.mockserver.client.serialization.ExpectationSerializer;
import org.mockserver.client.serialization.HttpRequestSerializer;
import org.mockserver.client.serialization.VerificationSequenceSerializer;
import org.mockserver.client.serialization.VerificationSerializer;
import org.mockserver.filters.RequestFilter;
import org.mockserver.filters.RequestResponseLogFilter;
import org.mockserver.filters.ResponseFilter;
import org.mockserver.mappers.HttpServletRequestToMockServerRequestDecoder;
import org.mockserver.mappers.MockServerResponseToHttpServletResponseEncoder;
import org.mockserver.model.*;
import org.mockserver.filters.RequestLogFilter;
import org.mockserver.verify.Verification;
import org.mockserver.verify.VerificationSequence;
import org.mockserver.verify.VerificationTimes;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import java.io.IOException;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertEquals;
import static org.mockito.AdditionalMatchers.aryEq;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.same;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.mockserver.model.Header.header;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.OutboundHttpRequest.outboundRequest;
public class ProxyServletTest {
@Mock
private HttpServletRequestToMockServerRequestDecoder mockHttpServletRequestToMockServerRequestDecoder;
@Mock
private MockServerResponseToHttpServletResponseEncoder mockServerResponseToHttpServletResponseEncoder;
@Mock
private NettyHttpClient mockNettyHttpClient;
@Mock
private RequestLogFilter mockRequestLogFilter;
@Mock
private RequestResponseLogFilter mockRequestResponseLogFilter;
@Mock
private HttpRequestSerializer mockHttpRequestSerializer;
@Mock
private ExpectationSerializer mockExpectationSerializer;
@Mock
private VerificationSerializer mockVerificationSerializer;
@Mock
private VerificationSequenceSerializer mockVerificationSequenceSerializer;
@InjectMocks
private ProxyServlet proxyServlet;
private MockHttpServletRequest mockHttpServletRequest;
private MockHttpServletResponse mockHttpServletResponse;
private OutboundHttpRequest outboundHttpRequest;
private HttpResponse httpResponse;
private ArgumentCaptor<OutboundHttpRequest> httpRequestArgumentCaptor;
@Before
public void setupMocks() {
// create mocks
proxyServlet = new ProxyServlet();
initMocks(this);
// additional mock objects
mockHttpServletRequest = new MockHttpServletRequest();
mockHttpServletResponse = new MockHttpServletResponse();
outboundHttpRequest = outboundRequest("localhost", 80, "", request().withHeader(header("Host", "localhost")).withPath("some_path"));
httpResponse = new HttpResponse();
// mappers
when(mockHttpServletRequestToMockServerRequestDecoder.mapHttpServletRequestToMockServerRequest(any(MockHttpServletRequest.class))).thenReturn(outboundHttpRequest);
httpRequestArgumentCaptor = ArgumentCaptor.forClass(OutboundHttpRequest.class);
when(mockNettyHttpClient.sendRequest(httpRequestArgumentCaptor.capture())).thenReturn(httpResponse);
}
@Test
public void shouldProxyGETRequest() {
// when
proxyServlet.doGet(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockHttpServletRequestToMockServerRequestDecoder).mapHttpServletRequestToMockServerRequest(same(mockHttpServletRequest));
verify(mockServerResponseToHttpServletResponseEncoder).mapMockServerResponseToHttpServletResponse(same(httpResponse), same(mockHttpServletResponse));
verify(mockNettyHttpClient).sendRequest(outboundHttpRequest);
}
@Test
public void shouldProxyHEADRequest() {
// when
proxyServlet.doHead(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockHttpServletRequestToMockServerRequestDecoder).mapHttpServletRequestToMockServerRequest(same(mockHttpServletRequest));
verify(mockServerResponseToHttpServletResponseEncoder).mapMockServerResponseToHttpServletResponse(same(httpResponse), same(mockHttpServletResponse));
verify(mockNettyHttpClient).sendRequest(outboundHttpRequest);
}
@Test
public void shouldProxyPOSTRequest() {
// when
proxyServlet.doPost(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockHttpServletRequestToMockServerRequestDecoder).mapHttpServletRequestToMockServerRequest(same(mockHttpServletRequest));
verify(mockServerResponseToHttpServletResponseEncoder).mapMockServerResponseToHttpServletResponse(same(httpResponse), same(mockHttpServletResponse));
verify(mockNettyHttpClient).sendRequest(outboundHttpRequest);
}
@Test
public void shouldProxyPUTRequest() {
// when
proxyServlet.doPut(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockHttpServletRequestToMockServerRequestDecoder).mapHttpServletRequestToMockServerRequest(same(mockHttpServletRequest));
verify(mockServerResponseToHttpServletResponseEncoder).mapMockServerResponseToHttpServletResponse(same(httpResponse), same(mockHttpServletResponse));
verify(mockNettyHttpClient).sendRequest(outboundHttpRequest);
}
@Test
public void shouldProxyDELETERequest() {
// when
proxyServlet.doDelete(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockHttpServletRequestToMockServerRequestDecoder).mapHttpServletRequestToMockServerRequest(same(mockHttpServletRequest));
verify(mockServerResponseToHttpServletResponseEncoder).mapMockServerResponseToHttpServletResponse(same(httpResponse), same(mockHttpServletResponse));
verify(mockNettyHttpClient).sendRequest(outboundHttpRequest);
}
@Test
public void shouldProxyOPTIONSRequest() {
// when
proxyServlet.doOptions(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockHttpServletRequestToMockServerRequestDecoder).mapHttpServletRequestToMockServerRequest(same(mockHttpServletRequest));
verify(mockServerResponseToHttpServletResponseEncoder).mapMockServerResponseToHttpServletResponse(same(httpResponse), same(mockHttpServletResponse));
verify(mockNettyHttpClient).sendRequest(outboundHttpRequest);
}
@Test
public void shouldProxyTRACERequest() {
// when
proxyServlet.doTrace(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockHttpServletRequestToMockServerRequestDecoder).mapHttpServletRequestToMockServerRequest(same(mockHttpServletRequest));
verify(mockServerResponseToHttpServletResponseEncoder).mapMockServerResponseToHttpServletResponse(same(httpResponse), same(mockHttpServletResponse));
verify(mockNettyHttpClient).sendRequest(outboundHttpRequest);
}
@Test
public void shouldCallMatchingFiltersBeforeForwardingRequest() {
// given
// - add first filter
RequestFilter filter = mock(RequestFilter.class);
proxyServlet.withFilter(outboundHttpRequest, filter);
// - add first filter with other request
HttpRequest someOtherRequest = request().withPath("some_other_path");
proxyServlet.withFilter(someOtherRequest, filter);
// - add second filter
RequestFilter someOtherFilter = mock(RequestFilter.class);
proxyServlet.withFilter(someOtherRequest, someOtherFilter);
// when
proxyServlet.doGet(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(filter, times(1)).onRequest(same(outboundHttpRequest));
verify(filter, times(0)).onRequest(same(someOtherRequest));
verifyZeroInteractions(someOtherFilter);
}
@Test
public void shouldApplyFiltersBeforeAndAfterRequest() {
// given
// - add first filter
ResponseFilter filter = mock(ResponseFilter.class);
when(filter.onResponse(any(HttpRequest.class), any(HttpResponse.class))).thenReturn(new HttpResponse());
proxyServlet.withFilter(outboundHttpRequest, filter);
// - add first filter with other request
HttpRequest someOtherRequest = request().withPath("some_other_path");
proxyServlet.withFilter(someOtherRequest, filter);
// - add second filter
ResponseFilter someOtherFilter = mock(ResponseFilter.class);
proxyServlet.withFilter(someOtherRequest, someOtherFilter);
// when
proxyServlet.doGet(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(filter, times(1)).onResponse(same(outboundHttpRequest), same(httpResponse));
verify(filter, times(0)).onResponse(same(someOtherRequest), same(httpResponse));
verifyZeroInteractions(someOtherFilter);
}
@Test
public void shouldNotForwardHopByHopHeaders() {
// given
outboundHttpRequest.withHeaders(
header("host", "localhost"),
header("some_other_header"),
header("proxy-connection"),
header("connection"),
header("keep-alive"),
header("transfer-encoding"),
header("te"),
header("trailer"),
header("proxy-authorization"),
header("proxy-authenticate"),
header("upgrade")
);
// when
proxyServlet.doGet(mockHttpServletRequest, mockHttpServletResponse);
// then
HttpRequest actual = httpRequestArgumentCaptor.getValue();
assertEquals(actual.getHeaders().size(), 2);
}
@Test
public void shouldDumpToLogAsJSON() {
// given
mockHttpServletRequest.setRequestURI("/dumpToLog");
mockHttpServletRequest.setContent("body".getBytes());
when(mockHttpRequestSerializer.deserialize("body")).thenReturn(outboundHttpRequest);
// when
proxyServlet.doPut(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockRequestResponseLogFilter).dumpToLog(outboundHttpRequest, false);
assertEquals(HttpStatusCode.ACCEPTED_202.code(), mockHttpServletResponse.getStatus());
}
@Test
public void shouldDumpToLogAsJava() {
// given
mockHttpServletRequest.setRequestURI("/dumpToLog");
mockHttpServletRequest.setContent("body".getBytes());
mockHttpServletRequest.addParameter("type", "java");
when(mockHttpRequestSerializer.deserialize("body")).thenReturn(outboundHttpRequest);
// when
proxyServlet.doPut(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockRequestResponseLogFilter).dumpToLog(outboundHttpRequest, true);
assertEquals(HttpStatusCode.ACCEPTED_202.code(), mockHttpServletResponse.getStatus());
}
@Test
public void shouldReturnRecordedRequests() throws IOException {
// given
MockHttpServletResponse httpServletResponse = new MockHttpServletResponse();
MockHttpServletRequest httpServletRequest = new MockHttpServletRequest("PUT", "/retrieve");
httpServletRequest.setContent("requestBytes".getBytes());
// and - a request matcher
HttpRequest request = new HttpRequest();
when(mockHttpRequestSerializer.deserialize(anyString())).thenReturn(request);
// and - a set of requests retrieved from the log
HttpRequest[] httpRequests = {request, request};
when(mockRequestLogFilter.retrieve(any(HttpRequest.class))).thenReturn(httpRequests);
when(mockHttpRequestSerializer.serialize(httpRequests)).thenReturn("request_response");
// when
proxyServlet.doPut(httpServletRequest, httpServletResponse);
// then
verify(mockRequestLogFilter).retrieve(request);
assertThat(httpServletResponse.getContentAsByteArray(), is("request_response".getBytes()));
assertThat(httpServletResponse.getStatus(), is(HttpStatusCode.OK_200.code()));
verifyNoMoreInteractions(mockHttpServletRequestToMockServerRequestDecoder);
}
@Test
public void shouldVerifyRequestNotMatching() throws IOException {
// given
MockHttpServletResponse httpServletResponse = new MockHttpServletResponse();
MockHttpServletRequest httpServletRequest = new MockHttpServletRequest("PUT", "/verify");
Verification verification = new Verification().withRequest(request()).withTimes(VerificationTimes.once());
String requestBytes = "requestBytes";
httpServletRequest.setContent(requestBytes.getBytes());
when(mockVerificationSerializer.deserialize(requestBytes)).thenReturn(verification);
when(mockRequestLogFilter.verify(verification)).thenReturn("verification_error");
// when
proxyServlet.doPut(httpServletRequest, httpServletResponse);
// then
verify(mockRequestLogFilter).verify(verification);
assertThat(httpServletResponse.getContentAsString(), is("verification_error"));
assertThat(httpServletResponse.getStatus(), is(HttpStatusCode.NOT_ACCEPTABLE_406.code()));
verifyNoMoreInteractions(mockHttpServletRequestToMockServerRequestDecoder);
}
@Test
public void shouldVerifyRequestMatching() throws IOException {
// given
MockHttpServletResponse httpServletResponse = new MockHttpServletResponse();
MockHttpServletRequest httpServletRequest = new MockHttpServletRequest("PUT", "/verify");
Verification verification = new Verification().withRequest(request()).withTimes(VerificationTimes.once());
String requestBytes = "requestBytes";
httpServletRequest.setContent(requestBytes.getBytes());
when(mockVerificationSerializer.deserialize(requestBytes)).thenReturn(verification);
when(mockRequestLogFilter.verify(verification)).thenReturn("");
// when
proxyServlet.doPut(httpServletRequest, httpServletResponse);
// then
verify(mockRequestLogFilter).verify(verification);
assertThat(httpServletResponse.getContentAsString(), is(""));
assertThat(httpServletResponse.getStatus(), is(HttpStatusCode.ACCEPTED_202.code()));
verifyNoMoreInteractions(mockHttpServletRequestToMockServerRequestDecoder);
}
@Test
public void shouldVerifySequenceRequestNotMatching() throws IOException {
// given
MockHttpServletResponse httpServletResponse = new MockHttpServletResponse();
MockHttpServletRequest httpServletRequest = new MockHttpServletRequest("PUT", "/verifySequence");
VerificationSequence verification = new VerificationSequence().withRequests(request("one"), request("two"));
String requestBytes = "requestBytes";
httpServletRequest.setContent(requestBytes.getBytes());
when(mockVerificationSequenceSerializer.deserialize(requestBytes)).thenReturn(verification);
when(mockRequestLogFilter.verify(verification)).thenReturn("verification_error");
// when
proxyServlet.doPut(httpServletRequest, httpServletResponse);
// then
verify(mockRequestLogFilter).verify(verification);
assertThat(httpServletResponse.getContentAsString(), is("verification_error"));
assertThat(httpServletResponse.getStatus(), is(HttpStatusCode.NOT_ACCEPTABLE_406.code()));
verifyNoMoreInteractions(mockHttpServletRequestToMockServerRequestDecoder);
}
@Test
public void shouldVerifySequenceRequestMatching() throws IOException {
// given
MockHttpServletResponse httpServletResponse = new MockHttpServletResponse();
MockHttpServletRequest httpServletRequest = new MockHttpServletRequest("PUT", "/verifySequence");
VerificationSequence verification = new VerificationSequence().withRequests(request("one"), request("two"));
String requestBytes = "requestBytes";
httpServletRequest.setContent(requestBytes.getBytes());
when(mockVerificationSequenceSerializer.deserialize(requestBytes)).thenReturn(verification);
when(mockRequestLogFilter.verify(verification)).thenReturn("");
// when
proxyServlet.doPut(httpServletRequest, httpServletResponse);
// then
verify(mockRequestLogFilter).verify(verification);
assertThat(httpServletResponse.getContentAsString(), is(""));
assertThat(httpServletResponse.getStatus(), is(HttpStatusCode.ACCEPTED_202.code()));
verifyNoMoreInteractions(mockHttpServletRequestToMockServerRequestDecoder);
}
@Test
public void shouldReset() {
// given
mockHttpServletRequest.setRequestURI("/reset");
// when
proxyServlet.doPut(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockRequestLogFilter).reset();
assertEquals(HttpStatusCode.ACCEPTED_202.code(), mockHttpServletResponse.getStatus());
}
@Test
public void shouldClear() {
// given
mockHttpServletRequest.setRequestURI("/clear");
mockHttpServletRequest.setContent("body".getBytes());
when(mockHttpRequestSerializer.deserialize("body")).thenReturn(outboundHttpRequest);
// when
proxyServlet.doPut(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockRequestLogFilter).clear(outboundHttpRequest);
assertEquals(HttpStatusCode.ACCEPTED_202.code(), mockHttpServletResponse.getStatus());
}
@Test
public void shouldMapPathWhenContextSet() {
// given
mockHttpServletRequest.setPathInfo("/clear");
mockHttpServletRequest.setContextPath("/mockserver");
mockHttpServletRequest.setRequestURI("/mockserver/clear");
mockHttpServletRequest.setContent("body".getBytes());
when(mockHttpRequestSerializer.deserialize("body")).thenReturn(outboundHttpRequest);
// when
proxyServlet.doPut(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockRequestLogFilter).clear(outboundHttpRequest);
assertEquals(HttpStatusCode.ACCEPTED_202.code(), mockHttpServletResponse.getStatus());
}
@Test
public void shouldMapPathWhenContextSetButPathNull() {
// given
mockHttpServletRequest.setPathInfo(null);
mockHttpServletRequest.setContextPath("/mockserver");
mockHttpServletRequest.setRequestURI("/clear");
mockHttpServletRequest.setContent("body".getBytes());
when(mockHttpRequestSerializer.deserialize("body")).thenReturn(outboundHttpRequest);
// when
proxyServlet.doPut(mockHttpServletRequest, mockHttpServletResponse);
// then
verify(mockRequestLogFilter).clear(outboundHttpRequest);
assertEquals(HttpStatusCode.ACCEPTED_202.code(), mockHttpServletResponse.getStatus());
}
}