If you want to
create a mock Http server for integration testing to mock external
URLS/Servers. Here is the solution for java.
I have gone through
the all options like WireMock, nanoHttpd,Mock-Server,LightWeightServer…etc but
not full fill my requirements and not easy to use for my use case.
I created my own
solution for this problem and of course inspired from other blogs to get into
this .
First use
Dependencies:
testCompile
group: 'org.mortbay.jetty', name: 'jetty', version: '7.0.0.pre5'
compile
'commons-io:commons-io:2.5'
Mortbay Jetty will
do simple and nice job here.
If you’re working with webserver
clients you will certainly have noticed the difficulty in integration-testing
your webserver clients. Building webserver clients can already be quite a
complex task, but providing a mock-up webservice backend delivering useful test
responses is quite often just to much work, if not impossible, since many web
server backends are very complex constructs. Furthermore, setting up a backend
for each integration test consumes valuable build time.
As an alternative, one may simply replace
the backend with a mock HTTP server that does one thing: deliver the expected
webserver response – i.e. XML data – when called by the client. All
you need to set this up is a HTTP server and a pre-recorded service response
(quite often this comes with WS client specifications). If you don’t have this
data, you can record it, for example using a proxy server in between your WS
client and a real WS backend, or a tool such as wireshark.
The recorded XML response thus
represents your assumptions against which you test the client. This makes your
tests fast, lightweight and a lot better to understand.
Server Code Here
package com.java.testing.httpclient;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.apache.commons.io.IOUtils.write;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.http.entity.ContentType;
import org.junit.Ignore;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.HttpConnection;
import org.mortbay.jetty.Request;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.handler.AbstractHandler;
import com.touchpeak.restclient.util.NullUtil;
/**
* Used for Mocking Http Server
*
* @author Kumar
*
*/
@Ignore
public class MockHttpTestServer {
private int HTTP_PORT = 55556;
private Server _server;
private String _responseBody;
private String _requestBody;
private String _mockResponseData;
private Integer _mockResponseStatus;
private String _mockResponseContentType;
private String _requestPath;
private String _requestMethod;
private Map requestedQueryParams = new HashMap<>();
public MockHttpTestServer() {
}
public MockHttpTestServer(int port) {
HTTP_PORT = port;
}
public MockHttpTestServer(String mockData) {
setMockResponseData(mockData);
}
public void start() throws Exception {
configureServer();
startServer();
}
private void startServer() throws Exception {
_server.start();
}
protected void configureServer() {
_server = new Server(HTTP_PORT);
_server.setHandler(getMockHandler());
}
/**
* Creates an {@link AbstractHandler handler} returning an arbitrary String
* as a response.
*
* @return never null.
*/
public Handler getMockHandler() {
Handler handler = new AbstractHandler() {
public void handle(String target, HttpServletRequest request,
HttpServletResponse response, int dispatch)
throws IOException, ServletException {
cleanInMemory();
Request baseRequest = request instanceof Request ? (Request) request
: HttpConnection.getCurrentConnection().getRequest();
setRequestMethod(baseRequest.getMethod());
setRequestPath(baseRequest.getUri().getPath());
setResponseBody(getMockResponseData());
setRequestBody(IOUtils.toString(baseRequest.getInputStream(),
"UTF-8"));
response.setStatus(getMockResponseStatus());
response.setContentType(getMockResponseContentType() != null ? getMockResponseContentType()
: "text/plain");
write(getResponseBody(), response.getOutputStream(), "UTF-8");
baseRequest.setHandled(true);
}
};
return handler;
}
protected void cleanInMemory() {
setRequestBody("");
setRequestPath("");
}
public void stop() throws Exception {
_server.stop();
}
public void setResponseBody(String responseBody) {
_responseBody = responseBody;
}
public String getResponseBody() {
return _responseBody;
}
public void setRequestBody(String requestBody) {
_requestBody = requestBody;
}
public String getRequestBody() {
return _requestBody;
}
public static void main(String[] args) {
MockHttpTestServer server = new MockHttpTestServer();
try {
server.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void setMockResponseData(String mockResponseData) {
_mockResponseData = mockResponseData;
}
public String getMockResponseData() {
return _mockResponseData;
}
protected Server getServer() {
return _server;
}
public Map getRequestedQueryParams() {
return requestedQueryParams;
}
public String getRequestPath() {
return _requestPath;
}
public String getMockResponseContentType() {
return _mockResponseContentType;
}
public void setMockResponseContentType(String _mockResponseContentType) {
this._mockResponseContentType = _mockResponseContentType;
}
public Integer getMockResponseStatus() {
return NullUtil.isNullOrEmpty(_mockResponseStatus) ? SC_OK
: _mockResponseStatus;
}
public void setMockResponseStatus(Integer _mockResponseStatus) {
this._mockResponseStatus = _mockResponseStatus;
}
public void setRequestPath(String _requestPath) {
this._requestPath = _requestPath;
}
public String getRequestMethod() {
return _requestMethod;
}
public void setRequestMethod(String _requestMethod) {
this._requestMethod = _requestMethod;
}
}
Client Code Here
package com.java.testing.httpclient;
import static org.junit.Assert.assertEquals;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.touchpeak.restclient.test.MockHttpTestServer;
public class HttpClientTests {
private static final Logger logger = LoggerFactory
.getLogger(HttpClientTests.class);
private MockHttpTestServer server;
private String HOST = "127.0.0.1";
private int PORT =56342;
private String TEST_BASE_URI = "http://"+HOST+":"+PORT;
@Before
public void init()
{
server = new MockHttpTestServer(PORT);
try {
server.start();
} catch (Exception e) {
logger.error(" While starting Mock Http Server ",e);
}
}
@After
public void close()
{
try {
server.stop();
} catch (Exception e) {
logger.error(" While stopping Mock Http Server ",e);
}
}
@Test
public void test_Server_Call()
{
String mockResponse = "Mock Response you expect from server";
String mockRequestBody ="RequestBody Sent to server from client";
server.setMockResponseData(mockResponse);
//Server will return above expected responses to client call.
String actualResponse = " write client code here to call server and get the response from server call";
assertEquals("GET", server.getRequestMethod());//Check HTTP METHOD here
assertEquals("/order/3?area=LONDON", server.getRequestPath());// Check Request URI
assertEquals(mockRequestBody, server.getRequestBody());//Check RequestBody received by Server
assertEquals(mockResponse, actualResponse);//check Response from server
}
}
Tips:
1. you can also add Listeners to Server class to get control back on client side while executing.
No comments:
Post a Comment
Please comment here