Showing posts with label mock server. Show all posts
Showing posts with label mock server. Show all posts

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 :)