I have a class GoogleApiClientWrapper
which basically handles interactions with Google for authentication and listing files and drives using Google Drive Java SDK version: v3-rev110-1.23.0.
I am using the following dependencies:
google-api-client:1.28.0
google-http-client:1.28.0
google-http-client-apache-2.0.0.jar
com.github.tomakehurst:wiremock-jre8:2.32.0
I am trying to unit test my class. So I thought about using WireMock Record & Playback feature to record the requests to Google APIs by routing the requests via WireMock to be able to record the responses for a given request.
So the idea is to create an instance of HttpTransport which is configured to proxy all requests to localhost on port 8443 which is the port WireMock is running on and inject this HttpTransport
to the GoogleRefreshTokenRequest
constructor or the Drive.Builder. Then WireMock is configured to proxy requests on localhost to the google api url. So ultimately the requests will be sent to google api the first time then after I am able to record the responses WireMock will be able to respond from the saved mappings.
Here it the implementation of GoogleRefreshTokenRequest
in GoogleApiClientWrapper
is as follows:
GoogleTokenResponse getGoogleTokenResponse(HttpTransport httpTransport,
JsonFactory jsonFactory,
String refreshToken,
String clientId,
String clientSecret,
List<String> exportScopes) throws IOException {
return new GoogleRefreshTokenRequest(httpTransport, jsonFactory, refreshToken, clientId, clientSecret)
.setScopes(exportScopes)
.execute();
}
Here is the test class with WireMock code to proxy the request and record the mappings.
public class GoogleApiWrapperTest {
@ClassRule
public static WireMockClassRule wireMockRule = new WireMockClassRule(WireMockConfiguration.wireMockConfig().httpsPort(8443));
@Test
public void testGetGoogleTokenResponse() throws IOException, GeneralSecurityException {
wireMockRule.startRecording("https://oauth2.googleapis.com/token");
GoogleApiClientWrapper clientWrapper= new GoogleApiClientWrapper();
HttpHost proxy = new HttpHost("127.0.0.1", 8443);
DefaultProxyRoutePlanner routePlanner = new DefaultProxyRoutePlanner(proxy);
HttpClient client = HttpClients.custom()
.setRoutePlanner(routePlanner)
.build();
HttpTransport httpTransport = new ApacheHttpTransport(client);
String clientId = "my-client-id";
String clientSecret = "my-client-secret";
String tokenString = "sometoken";
String refreshToken = tokenString.split("\\|")[0];
GoogleTokenResponse actual = clientWrapper.getGoogleTokenResponse(httpTransport,JacksonFactory.getDefaultInstance(),refreshToken,clientId,clientSecret,Arrays.asList(DriveScopes.DRIVE_READONLY));
wireMockRule.stopRecording().getStubMappings();
}
}
The following code will be removed from the test class once mapping created:
wireMockRule.startRecording("https://oauth2.googleapis.com/token");
wireMockRule.stopRecording().getStubMappings();
When I run it I get the following exception:
org.apache.http.client.ClientProtocolException
Caused by: org.apache.http.ProtocolException: The server failed to respond with a valid HTTP response
I also tried to create the HttpTransport as follows based on this answer
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.0", 8443));
HttpTransport httpTransport = new NetHttpTransport.Builder().setProxy(proxy).build();
How to solve this issue or is there a missing configuration for the HttpTransport
or for the WireMockClassRule? Or is there an easier way to be able to store the google api responses via WireMock?
I already used Mockito to mock the responses when testing other classes that use the GoogleApiClientWrapper
class but in this unit test I want to try to test the behaviour.