Ratpacked: Use TestHttpClient For External HTTP Services
Ratpack has a very useful class: TestHttpClient
.
This is a blocking HTTP client that we normally use for testing our Ratpack applications.
For example we use MainClassApplicationUnderTest
or GroovyRatpackMainApplicationUnderTest
in a test and invoke the getHttpClient
method to get an instance of TestHttpClient
.
The class has a lot of useful methods to make HTTP requests with a nice DSL.
TestHttpClient
is also very useful as a standalone HTTP client in other applications.
Suppose we have a piece of code that needs to access MapQuest Open Platform Web Services to get location details for a given combination of longitude and latitude values.
In the constructor we create an instance of the interface ApplicationUnderTest
.
We then can use the getHttpClient
method of ApplicationUnderTest
to get a TestHttpClient
instance:
// File: src/main/groovy/mrhaki/geocode/GeocodeService.groovy
package mrhaki.geocode
import groovy.json.JsonSlurper
import ratpack.http.client.ReceivedResponse
import ratpack.test.ApplicationUnderTest
import ratpack.test.http.TestHttpClient
class GeocodeService {
private final ApplicationUnderTest mapQuestApi
private final GeocodeConfig config
GeocodeService(final GeocodeConfig config) {
this.config = config
// Create ApplicationUnderTest using a Closure,
// which returns the URI of our external HTTP service.
// The ApplicationUnderTest interface only
// has one method (URI getAddress()),
// so we can use a Closure to implement the interface.
mapQuestApi = { config.uri.toURI() }
}
Location getLocation(final Double latitude, final Double longitude) {
// Create a blocking HttpClient with the base
// URI from ApplicationUnderTest.
final TestHttpClient httpClient = mapQuestApi.httpClient
// Request location details for given latitude and longitude
// and set the application key.
httpClient.params { paramBuilder ->
paramBuilder.put 'key', config.apiKey
paramBuilder.put 'location', \[latitude, longitude\].join(',')
}
// Use get method to get a response from the HTTP service.
final ReceivedResponse response = httpClient.get('geocoding/v1/reverse')
// Transform JSON result and
// find location specific details in the response.
final jsonResponse = new JsonSlurper().parseText(response.body.text)
final location = jsonResponse.results\[0\].locations\[0\]
// Create new Location object.
new Location(street: location.street, city: location.adminArea5)
}
}
The host name and key we need to make a request are set via the GeocodeConfig
class:
// File: src/main/groovy/mrhaki/geocode/GeocodeConfig.groovy
package mrhaki.geocode
class GeocodeConfig {
String apiKey
String uri
}
And finally a simple POGO to store the location details:
// File: src/main/groovy/mrhaki/geocode/Location.groovy
package mrhaki.geocode
import groovy.transform.Immutable
@Immutable
class Location {
String street
String city
}
In our project we only have to add a dependency on io.ratpack:ratpack-test
:
// File: build.gradle
...
dependencies {
...
compile group: 'io.ratpack', name: 'ratpack-test', version: '1.3.3'
...
}
...
Written with Ratpack 1.3.3.