Documentation

You are viewing the documentation for the 2.8.x release series. The latest stable release series is 3.0.x.

§Testing web service clients

A lot of code can go into writing a web service client - preparing the request, serializing and deserializing the bodies, setting the correct headers. Since a lot of this code works with strings and weakly typed maps, testing it is very important. However testing it also presents some challenges. Some common approaches include:

§Test against the actual web service

This of course gives the highest level of confidence in the client code, however it is usually not practical. If it’s a third party web service, there may be rate limiting in place that prevents your tests from running (and running automated tests against a third party service is not considered being a good netizen). It may not be possible to set up or ensure the existence of the necessary data that your tests require on that service, and your tests may have undesirable side effects on the service.

§Test against a test instance of the web service

This is a little better than the previous one, however it still has a number of problems. Many third party web services don’t provide test instances. It also means your tests depend on the test instance being running, meaning that test service could cause your build to fail. If the test instance is behind a firewall, it also limits where the tests can be run from.

§Mock the http client

This approach gives the least confidence in the test code - often this kind of testing amounts to testing no more than that the code does what it does, which is of no value. Tests against mock web service clients show that the code runs and does certain things, but gives no confidence as to whether anything that the code does actually correlates to valid HTTP requests being made.

§Mock the web service

This approach is a good compromise between testing against the actual web service and mocking the http client. Your tests will show that all the requests it makes are valid HTTP requests, that serialization/deserialization of bodies work, etc, but they will be entirely self contained, not depending on any third party services.

Play provides some helper utilities for mocking a web service in tests, making this approach to testing a very viable and attractive option.

§Testing a GitHub client

As an example, let’s say you’ve written a GitHub client, and you want to test it. The client is very simple, it just allows you to look up the names of the public repositories:

import com.fasterxml.jackson.databind.JsonNode;
import java.util.*;
import java.util.concurrent.CompletionStage;
import java.util.stream.Collectors;
import javax.inject.Inject;
import play.libs.ws.WSClient;

class GitHubClient {
  private WSClient ws;

  @Inject
  public GitHubClient(WSClient ws) {
    this.ws = ws;
  }

  String baseUrl = "https://api.github.com";

  public CompletionStage<List<String>> getRepositories() {
    return ws.url(baseUrl + "/repositories")
        .get()
        .thenApply(
            response ->
                response.asJson().findValues("full_name").stream()
                    .map(JsonNode::asText)
                    .collect(Collectors.toList()));
  }
}

Note that it takes the GitHub API base URL as a parameter - we’ll override this in our tests so that we can point it to our mock server.

To test this, we want an embedded Play server that will implement this endpoint. We can do that by Creating an embedded server with the