Step 1. Add the JitPack repository to your build file
Add it in your root settings.gradle at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url 'https://jitpack.io' }
}
}
Add it in your settings.gradle.kts at the end of repositories:
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
maven { url = uri("https://jitpack.io") }
}
}
Add to pom.xml
<repositories>
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
Add it in your build.sbt at the end of resolvers:
resolvers += "jitpack" at "https://jitpack.io"
Add it in your project.clj at the end of repositories:
:repositories [["jitpack" "https://jitpack.io"]]
Step 2. Add the dependency
dependencies {
implementation 'com.github.kristofa:mock-http-server:mock-http-server-4.1'
}
dependencies {
implementation("com.github.kristofa:mock-http-server:mock-http-server-4.1")
}
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>mock-http-server</artifactId>
<version>mock-http-server-4.1</version>
</dependency>
libraryDependencies += "com.github.kristofa" % "mock-http-server" % "mock-http-server-4.1"
:dependencies [[com.github.kristofa/mock-http-server "mock-http-server-4.1"]]
This project is archived and not maintained anymore. The repo remains read-only and can be forked. I suggest you to look at similar projects that are still maintained like wiremock or mockwebserver
MockHttpServer is available through Maven Central so you can get it by including following dependency in your pom.xml:
<dependency>
<groupId>com.github.kristofa</groupId>
<artifactId>mock-http-server</artifactId>
<version>4.1</version>
<scope>test</scope>
</dependency>
MockHttpServer is used to facilitate integration testing of Java applications that rely on external http services (eg REST services). MockHttpServer acts as a replacement for the external services and is configured to return specific responses for given requests.
Features:
Advantages:
(*) I got the term System Under Test from following post.
See also following posts by Martin Fowler: Self Initializing Fake and Integration Contract Test.

There are also other solutions to this problem which might be a better fit to your needs or which might be more mature: wiremock, rest-driver, mockwebserver.
public class MockHttpServerTest {
private static final int PORT = 51234;
private static final String baseUrl = "http://localhost:" + PORT;
private MockHttpServer server;
private SimpleHttpResponseProvider responseProvider;
private HttpClient client;
@Before
public void setUp() throws Exception {
responseProvider = new SimpleHttpResponseProvider();
server = new MockHttpServer(PORT, responseProvider);
server.start();
client = new DefaultHttpClient();
}
@After
public void tearDown() throws Exception {
client.getConnectionManager().shutdown();
server.stop();
}
@Test
public void testShouldHandleGetRequests() throws ClientProtocolException, IOException, UnsatisfiedExpectationException {
// Given a mock server configured to respond to a GET / with "OK"
responseProvider.expect(Method.GET, "/").respondWith(200, "text/plain", "OK");
// When a request for GET / arrives
final HttpGet req = new HttpGet(baseUrl + "/");
final HttpResponse response = client.execute(req);
final String responseBody = IOUtils.toString(response.getEntity().getContent());
final int statusCode = response.getStatusLine().getStatusCode();
// Then the response is "OK"
assertEquals("OK", responseBody);
// And the status code is 200
assertEquals(200, statusCode);
// Check there were no unexpected requests.
server.verify();
}
When creating an instance of MockHttpServer you have to provide a port and a HttpResponseProvider
instance. The HttpResponseProvider is the one being configured with request/responses.
When you want to configure rather simple requests/responses you can use SimpleHttpResponseProvider
as shown in above piece of code.
MockHttpServer is started by calling start() and is stopped by calling stop().
You can execute verify() when your test completed to make sure you got all and only your
expected requests. verify() will throw a UnsatisfiedExpectationException when this is not the case.

We have software that interacts with multiple external services and several of these services return complex entities as part of their responses. Building those responses by hand in the source files might not be the best solution. Also in some cases binary entities are returned.
LoggingHttpProxy is a proxy server that can be configured to sit in between our 'system under test' and
the external services. LoggingHttpProxy is configured to know how to forward requests it receives from
the 'system under test' to the external services. When it received the answer from the external services it
will return it to the 'system under test'.
What is special is that the LoggingHttpProxy can log and persist all the requests/responses. These persisted requests/responses can be replayed by MockHttpServer.

When you configure LoggingHttpProxy to use HttpRequestResponseFileLoggerFactory the
requests/responses will be persisted to files. These requests/responses can be replayed
by MockHttpServer by using FileHttpResponseProvider.

We assume that you start from an integration test in which case the software you want to test communicates with an external service and the test runs green. You want to mock the communication with the external service as it might be unreliable or even disappear.
You can use MockHttpServer or LoggingHttpProxy by themselves but since 2.0-SNAPSHOT
it is advised to use MockAndProxyFacade which will make it a lot easier. See following code
example:
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.junit.Test;
import com.github.kristofa.test.http.MockAndProxyFacade.Builder;
import com.github.kristofa.test.http.MockAndProxyFacade.Mode;
import com.github.kristofa.test.http.file.FileHttpResponseProvider;
import com.github.kristofa.test.http.file.HttpRequestResponseFileLoggerFactory;
public class MockHttpRequestTest {
// Host of original service. Service which we in the end want to replace with our mock implementation.
private final static String SERVICE_HOST = "host.domain";
// Port for host.
private final static int SERVICE_PORT = 8080;
// The port at which our mock or proxy will be running.
private final static int MOCK_AND_PROXY_PORT = 51235;
private final static String MOCK_PROXY_URL = "http://localhost:" + MOCK_AND_PROXY_PORT;
// Requests and responses will be logged to src/test/resources.
// This is what you typically want to do and check them in with your source code.
private final static String REQUEST_LOG_DIR = "src/test/resources/";
// We make sure our persisted request/responses have a unique name. Name of test class
// is probably a good choice.
private final static String REQUEST_LOG_FILE_NAME = "MockHttpRequestTest";
@Test
public void test() throws IOException, UnsatisfiedExpectationException {
// Initially you will want to log your existing requests. So you can put it to Mode.LOGGING.
// Once they are logged you can switch to MOCKING to replay persisted requests/responses.
// Changing this mode is the only thing you need to do. Your remaining test code stays the same.
final MockAndProxyFacade facade = buildFacade(Mode.LOGGING);
facade.start();
try {
// Execute your test code that will exercise mock or proxy depending on mode of operation for our facade.
final HttpClient httpClient = new DefaultHttpClient();
try {
final HttpGet req1 = new HttpGet(MOCK_PROXY_URL + "/service/a");
final HttpResponse response1 = httpClient.execute(req1);
assertEquals(200, response1.getStatusLine().getStatusCode());
} finally {
httpClient.getConnectionManager().shutdown();
}
// Verify that we got all and only the requests we expected.
facade.verify();
} finally {
facade.stop();
}
}
private MockAndProxyFacade buildFacade(final Mode mode) {
final Builder builder = new Builder();
return builder
.mode(mode)
.addForwardHttpRequestBuilder(new PassthroughForwardHttpRequestBuilder(SERVICE_HOST, SERVICE_PORT))
.httpRequestResponseLoggerFactory(
new HttpRequestResponseFileLoggerFactory(REQUEST_LOG_DIR, REQUEST_LOG_FILE_NAME)).port(MOCK_AND_PROXY_PORT)
.httpResponseProvider(new FileHttpResponseProvider(REQUEST_LOG_DIR, REQUEST_LOG_FILE_NAME)).build();
}
}
Important: You can't copy and run this code as is. It compiles and is valid but the http request will fail as there is no service at http://host.domain:8080. It is just an example for you to reuse.
This code example shows the usage of MockAndProxyFacade. This is a facade around MockHttpServer and LoggingHttpProxy and has as
purpose to switch between both with as least impact on test code as possible.
As you can see in the buildFade(Mode) method the MockAndProxyFacade is created using a Builder. The Builder handles configuration for both Logging as Mocking mode.
Mandatory Builder parameters (required for both mocking and logging modes):
Builder parameters mandatory for LOGGING mode:
PassthroughForwardHttpRequestBuilder which
simply adapts the host and port to the service we want to mock. This is what we want to typically do.HttpRequestResponseLogger instances that will be used to log requests/responses. In this
example we use and HttpRequestResponseFileLoggerFactory which will persist them to disk so we can replay them with MockHttpServer.Builder parameters mandatory for MOCKING mode:
FileHttpResponseProvider which will use the requests/responses
persisted by HttpRequestResponseFileLoggerFactory. Notice HttpRequestResponseFileLoggerFactory and FileHttpResponseProvider are configured with same directory and filename
values. This will make sure FileHttpResponseProvider will pick up requests/responses persisted during LOGGING mode.So if we want to switch between mocking and logging mode, because we expect our depend service is changed, we can simply change the mode parameter we pass to the buildFade(Mode)
method. The remaining test code and logic stays the same.
Advantages of this approach:
As of version 4.0-SNAPSHOT support is added for matching variable, non deterministic content in http requests.
An example of variable content can be a JSON entity. JSON does not specify a fixed order of properties so when serializing JSON the order of the properties can be different from 1 run to the other.
By default mock-http-server does an exact match of http requests, including entities.
To change the matching logic you can implement a HttpRequestMatchingFilter that you
can set in any of the available HttpResponseProvider instances.
Also HttpRequestMatchingFilter instances can be chained so you can set use multiple.
If you would have json entities but also other variable content like access tokens you
can build 2 HttpRequestMatchingFilter instances, 1 for each purpose and chain them.
There are some examples of Http Request Matching Filters that you can inspect:
If you want to contribute, this is a list of wanted functionality:
MockHttpServer selects a free port when 0 is passed as port number. This prevents conflicts as opposed to always taking a fixed port which can already be in used. Used port is returned by startmethod and there is also a new getPortmethod.DefaultHttpResponseProviderhas a resetmethod which allows reseting its state.Major version bump because custom matching of http requests, introduced in 3.0, has been reworked.
When using version 3.0 in real use cases it became clear that it was sub optimal.
4.0-SNAPSHOT has a better implementation of custom matching and major cleanup of existing
HttpResponseProvider instances.
HttpRequestResponseFileLoggerFactory has the option to delete previously logged requests/responses.
This prevents potential test failures if your new log session has less request/responses than previous one or if the requests/responses come in different order.
In reality most people manually deleted previously logged files. Now it can be done automatically through optional constructor argument.Major version bump because HttpResponseProvider interface has a new method.
Code that worked with 2.0 will also still work with 3.0 but if you have written your own HttpResponseProvider instances they will need adaptation and will not compile anymore.
HttpRequestMatcher which allows you to match http requests on part of their content. Can also be used to match http requests that have variable content. For example a
UUID that is generated and part of the request and which will be always different.
You can add custom HttpRequestMatcher instances to HttpResponseProvider instances which will than be used for matching.Version bump because the changes explained in 1st, 2nd and 3rd main bullet points can lead to failing tests that worked with 1.3 or earlier. The api is still the same but the behaviour is different.
MockHttpServer and LoggingHttpProxy in line (by sharing code and removing some code duplication).
MockHttpServer that indicates no matching request is found from 500 to 598.LoggingHttpProxy so that original requests/responses are not modified. Previously some http headers could be added when they were not provided for example User-Agent.HttpRequestFileReaderImpl supports message headers / key value pairs with multiple 'equal signs'. We now support for example: ContentType=application/json; charset=UTF-8.HttpResponseFileWriterImpl supports responses without Content-Type.MockHttpServer by catching any exception that occurs, log it, and return specific response code which is configurable (default=599).MockAndProxyFacade which makes it a lot more easy to switch between 'logging request' mode and 'mocking' mode. There is an integration test ITMockAndProxyFacade that shows how it works.First release