August 20, 2019

API Mocking / Simulation Tool Comparison

So we have seen Hoverfly and Wiremock API Simulations tools earlier and looked at Java examples of using them. Lets look at how both of them compare on various parameters and which one is best fit for your use-case.
We will do a comparison based on the few parameters as below and look at limitations and advantages over each other
  • Support for Capture Replay : Ability to capture the requests once and replay them during simulation
  • Support for HTTPS : Support for Https based API's
  • Client Side required changes : Changes required at the client, if any
  • Support for Stateful API's : Support for states when using stateful API's
  • Support for Response Templating : Ability to templatize responses to give dynamic behavior
  • Miscellaneous : Other miscellaneous parameters and unique features

Hoverfly

Hoverfly released under Apache 2.0 license primarily written using Go language is developed and maintained by SpectoLabs.

Support for Capture Replay

Capture is only supported in Proxy mode and is not supported in Web-Server mode. The captured requests can be exported to a Json file. Hoverfly has clear, defined and documented Simulation Schema.

Support for HTTPS

Proxy mode has the support for capture, simulate HTTPS API's and can use custom generated certificates for authentication. The Web-Server mode does not support HTTPS.

As it acts as forward proxy HTTPS is directly to and fro actual end-point. It also requires client to support the HTTP protocol to make the initial connection.

Client Side Changes

The client used should support and honor the 'Proxy Settings' that needs to be configured for using the tool. As the capture works in forward proxy no changes are required on the client side.

Support for Stateful API's

Hoverfly supports simulation of stateful API's. You can define states and give each requests a current state for matching and next transition state to move to the new state.

Support for Response Templating

Hoverfly supports response templatization to build dynamic responses. It comes with few predefined helper templates and uses a library based on handlebars for templating.

Miscellaneous

  • One of the main features of hoverfly is use of forward proxy. It allows to run in what is called as SPY mode where few API call can be simulated while the non-matching ones can call the real API.
  • Supports multiple endpoints for capture/simulation.
  • Has support for importing/resetting simulations at runtime. 
  • Ability to capture all the headers or specific mentioned headers
  • Provides Python and Java bindings
  • Allows Man in the Middle behavior for both HTTP and HTTPS through the use of middleware mode
  • Documented Simulation Schema 

Wiremock

Wiremock also released under Apache 2.0 license is written in Java, developed and maintained by Tom Akehurst

Support for Capture Replay

Capture is supported and there is the old (legacy) as well as the new way to capture the requests. Captured requests can be exported in Json file. Each request is exported to a separate file.

Support for HTTPS

Wiremock provides support for HTTPS and can use custom generated certificates for authentication. As it acts as reverse-proxy the actual end point is HTTPS details are hidden. The wire-mock server acts as the endpoint for the client.

Client side changes

The endpoint should be changed to point to wiremock server which can act as the reverse proxy for the actual endpoint during the capturing of requests.

Support for Stateful API's

Stateful API's are supported through Scenarios. You can define Scenario names and the different states in the scenarios which the request will match and transition during simulation. The legacy method of capture does not support stateful capture.

Support for Response Templating

Templatization is supported through the handlebars library. It contains the string and other helpers provided by the Java implementation of handlebars by jknack

Miscellaneous

  • Due to reverse proxy nature the clients are independent of the protocol of the actual endpoint
  • Has support for forward-proxy via enable-browser-proxy

Final Thoughts

So now that we have looked into both the tools lets look at what are few advantages and limitations over each other. The list is in no way complete but can act as a quick guide to identify which tools better fits your use-case.

Hoverfly Advantages

  • Support for SPY Mode where few API's are simulated while others are passed to the real endpoint
  • Defined and Documented Simulation Schema
  • Run-time importing/resetting of the simulations
  • Supports multiple endpoint with single instance (at-least in the proxy mode)

Hoverfly Limitation

  • Cannot capture requests in webserver mode
  • Web-server mode does not support HTTPS
  • Dependent on the client for support and use of system/manual proxy settings

Wiremock Advantages

  • Independent of the protocol of the actual endpoint
  • No configuration/changes required by the client.

Wiremock Limitations

  • Runtime import/resetting of simulations not supported. Simulation mappings needs to be defined at the start during creation/initialization.
  • Cannot capture all headers. Needs a list of the headers that needs to be captured.
  • Simulation Schema though defined is not documented completely anywhere.
  • Only one endpoint can be used with one instance. (Capture needs to be specified with a target url).

July 19, 2019

HTTP API Simulation using Wiremock


In today's world of micro-services we typically integrate to many REST API (working on HTTP or HTTPS) for our application. We already saw one such simulation tool called Hoverfly.

Wiremock is another similar tool for simulation of the API's. Take a look at the documentation of the tool. It supports both standalone (or command-line) mode as well as Java API.

Lets look at a sample API simulation example using Wiremock with Java.

We will use maven to create a new application and add the following dependency
<dependency>
    <groupId>com.github.tomakehurst</groupId>
    <artifactId>wiremock-jre8</artifactId>
    <version>2.23.2</version>
</dependency>

Once the dependencies are installed we want to instantiate and start WireMock as below :
WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.wireMockConfig()
//        .dynamicPort()
//        .usingFilesUnderDirectory("~/simulation/")
          .port(8888));

wireMockServer.getOptions().filesRoot().child(WireMockApp.MAPPINGS_ROOT).createIfNecessary();
wireMockServer.getOptions().filesRoot().child(WireMockApp.FILES_ROOT).createIfNecessary();

wireMockServer.start();

Note that above before starting the server we actually create the necessary directories where the simulation files will get stored. They are stored under 'mappings' (as given by MAPPING_ROOT) and '__files' (as given by FILES_ROOT) under the root directory. The default root directory is 'src/test/resources'.

Once the server is started we want to start recording and capture the requests. This can be done as below :
// Start Recording the request and proxy all the requests to http://echo.jsontest.com
wireMockServer.startRecording("http://echo.jsontest.com/");

// Create a client to call the echo url. Note that we are calling 
// the wiremock server which will act as a proxy to the configured url
HttpClient client = HttpClientFactory.createClient();
HttpGet request = new HttpGet("https://localhost:8888/a/b/c/d");
HttpResponse response = client.execute(request);

System.out.println("Response Code : " + response.getStatusLine().getStatusCode());
BufferedReader rd = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));
StringBuffer result = new StringBuffer();
String line = "";
while ((line = rd.readLine()) != null) {
    result.append(line);
}
System.out.println(result.toString());

// Stop the recording. The recorded mapping are stored inside the root directory
// and returned as result
SnapshotRecordResult recordedMappings = wireMockServer.stopRecording();

So now we have captured the recording it is time to test the simulated response. Here the recording is stopped but the wiremock server is still running. It will serve all the captured responses for similar requests.
Lets try it out
// We call the same URL and this time we will get simulated response
HttpGet same_request = new HttpGet("https://localhost:8888/a/b/c/d");
HttpResponse simulated_response = client.execute(same_request);
System.out.println("Response Code : " + simulated_response.getStatusLine().getStatusCode());
BufferedReader simBR = new BufferedReader(new InputStreamReader(simulated_response.getEntity().getContent()));
StringBuffer simBuffer = new StringBuffer();
line = "";
while ((line = simBR.readLine()) != null) {
    simBuffer.append(line);
}
System.out.println(simBuffer.toString());

// We call a different URL. As this is not captured it will return Not Found in the response
HttpGet different_request = new HttpGet("https://localhost:8888/e/f/g/h");
HttpResponse no_response = client.execute(different_request);
System.out.println("Response Code : " + no_response.getStatusLine().getStatusCode());
BufferedReader noBR = new BufferedReader(new InputStreamReader(no_response.getEntity().getContent()));
StringBuffer noBuffer = new StringBuffer();
line = "";
while ((line = noBR.readLine()) != null) {
    noBuffer.append(line);
}
System.out.println(noBuffer.toString());

At the end we need to stop the wiremock server as below
wireMockServer.stop();

Above we used record-replay to simulate the endpoints. Wiremock also provides methods for creating custom responses by using stub().

So happy simulating :)


June 29, 2019

Mocking API Requests using Hoverfly Java

 In today's world of micro-services we typically integrate to many REST API (working on HTTP or HTTPS) for our application. For development and testing we need an environment to work with those API. For this typically we write stubs or create a test-web-server to simulate those API. 

Hoverfly is one such tool that allows us to have API simulation. Take a look at the documentation of the tool in the standalone (or command-line) mode (Check out the basic tutorial). Its pretty straight forward and simple.

For development it may be feasible to use the command-line tool, but for the automated tests in the build process having this setup may be a bit of effort to setup the environment and use it. 
Instead Hoverfly also has Java (and Python) bindings for the tool that we can use in the automation.

Lets look at a sample mock API example using Java.

We will be using maven to create a new application and add the following dependency

 <dependency>
     <groupId>io.specto</groupId>
     <artifactId>hoverfly-java</artifactId>
     <version>0.12.0</version>
 </dependency>

Also make sure you are setting the Java compiler version in the properties

<properties>
    <!-- other properties, if any -->
    <maven.compiler.source>1.8</maven.compiler.source>
    <maven.compiler.target>1.8</maven.compiler.target>
</properties>

Now lets use hoverfly to capture and store the requests :
// Initialize Hoverfly instance
try (Hoverfly hoverfly = new Hoverfly(HoverflyConfig.localConfigs().captureHeaders("Content-Type", "Date"), HoverflyMode.CAPTURE)) {
    // Start hover-fly
    hoverfly.start();
    
    // Create a client to execute http requests. OkHttpClient comes bundled with Hoverfly. You can use any http-client.
    OkHttpClient client = new OkHttpClient();
    Request dateReq = new Request.Builder().url("http://date.jsontest.com").build();
    
    try (Response response = client.newCall(dateReq).execute()) {
        System.out.println("REAL : " + response.body().string());
    } catch (IOException e) {
        e.printStackTrace();
    }
    
    // Save/Export the response to a file
    hoverfly.exportSimulation(Paths.get(System.getProperty("user.dir"), "capture_requests.json"));
}
You can check the capture_requests.json to view the request-response that got saved.
Now lets simulate the request
// Initialize Hoverfly in what they call SPY mode
try (Hoverfly hoverfly = new Hoverfly(HoverflyConfig.localConfigs(), HoverflyMode.SPY)) {
    hoverfly.start();
    
    // Initialize client to making http request
    OkHttpClient client = new OkHttpClient();
    
    // As we have not yet imported any simulation, we will get the response from the real API call
    Request timeReq = new Request.Builder().url("http://time.jsontest.com").build();
    Request dateReq = new Request.Builder().url("http://date.jsontest.com").build();

    try (Response response = client.newCall(timeReq).execute()) {
        System.out.println("REAL : " + response.body().string());
    }
    
    try (Response response = client.newCall(dateReq).execute()) {
        System.out.println("REAL : " + response.body().string());
    }
    
    // Now lets import the simulation.
    // Remember we had captured 'date.jsontest' request which will give simulated responss. Any other requests
    // will still call the real API and give the response
    hoverfly.simulate(SimulationSource.file(Paths.get(System.getProperty("user.dir"), "capture_requests.json")));
    
    try (Response response = client.newCall(timeReq).execute()) {
        System.out.println("REAL : " + response.body().string());
    }
    
    try (Response response = client.newCall(dateReq).execute()) {
        System.out.println("SIMULATED : " + response.body().string());
    }
} 
Above we used captured request simulation but you can easily build your own simulation quickly using what they call 'dsl'
So lets start Simulating :)