Skip to content
This repository was archived by the owner on Sep 26, 2023. It is now read-only.

Commit b06fc12

Browse files
authored
Add MockHttpService (#492)
MockHttpService is used by discogapic generated unit tests. It operates similarly to the gapic MockService objects in that this mock service catches all incoming requests, and registers and returns expected responses/exceptions.
1 parent 970be44 commit b06fc12

File tree

5 files changed

+258
-37
lines changed

5 files changed

+258
-37
lines changed

gax-httpjson/src/main/java/com/google/api/gax/httpjson/ApiMethodDescriptor.java

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,19 @@
3131

3232
import com.google.api.client.http.HttpMethods;
3333
import com.google.api.core.BetaApi;
34+
import com.google.api.core.InternalApi;
3435
import com.google.auto.value.AutoValue;
36+
import com.google.common.collect.ImmutableSet;
3537
import com.google.gson.Gson;
3638
import com.google.gson.GsonBuilder;
3739
import com.google.gson.TypeAdapter;
3840
import com.google.gson.stream.JsonReader;
3941
import com.google.gson.stream.JsonWriter;
40-
import java.io.IOException;
4142
import java.io.Reader;
4243
import java.lang.reflect.Type;
4344
import java.util.HashSet;
4445
import java.util.Set;
46+
import javax.annotation.Nullable;
4547

4648
@BetaApi
4749
@AutoValue
@@ -53,10 +55,12 @@ public abstract class ApiMethodDescriptor<RequestT, ResponseT> {
5355

5456
public abstract Gson getRequestMarshaller();
5557

58+
@Nullable
5659
public abstract Gson getResponseMarshaller();
5760

5861
public abstract Type getRequestType();
5962

63+
@Nullable
6064
public abstract Type getResponseType();
6165

6266
// The name of the field in the RequestT that contains the resource name path.
@@ -78,46 +82,50 @@ public abstract class ApiMethodDescriptor<RequestT, ResponseT> {
7882
private static <RequestT, ResponseT> ApiMethodDescriptor<RequestT, ResponseT> create(
7983
String fullMethodName,
8084
RequestT requestInstance,
81-
ResponseT responseInstance,
85+
@Nullable ResponseT responseInstance,
8286
String endpointPathTemplate,
8387
String resourceNameField,
8488
Set<String> queryParams,
8589
HttpRequestFormatter<RequestT> httpRequestFormatter,
8690
String httpMethod) {
8791
final Type requestType = requestInstance.getClass();
88-
final Type responseType = responseInstance.getClass();
8992
final Gson baseGson = new GsonBuilder().create();
9093

9194
TypeAdapter requestTypeAdapter =
9295
new TypeAdapter<RequestT>() {
9396
@Override
94-
public void write(JsonWriter out, RequestT value) throws IOException {
97+
public void write(JsonWriter out, RequestT value) {
9598
baseGson.toJson(value, requestType, out);
9699
}
97100

98101
@Override
99-
public RequestT read(JsonReader in) throws IOException {
102+
public RequestT read(JsonReader in) {
100103
return null;
101104
}
102105
};
103106

104-
TypeAdapter responseTypeAdapter =
105-
new TypeAdapter<ResponseT>() {
106-
@Override
107-
public void write(JsonWriter out, ResponseT value) throws IOException {
108-
throw new UnsupportedOperationException("Unnecessary operation.");
109-
}
110-
111-
@Override
112-
public ResponseT read(JsonReader in) throws IOException {
113-
return baseGson.fromJson(in, responseType);
114-
}
115-
};
116-
117107
Gson requestMarshaller =
118108
new GsonBuilder().registerTypeAdapter(requestType, requestTypeAdapter).create();
119-
Gson responseMarshaller =
120-
new GsonBuilder().registerTypeAdapter(responseType, responseTypeAdapter).create();
109+
110+
TypeAdapter responseTypeAdapter = null;
111+
final Type responseType = responseInstance == null ? null : responseInstance.getClass();
112+
Gson responseMarshaller = null;
113+
if (responseInstance != null) {
114+
responseTypeAdapter =
115+
new TypeAdapter<ResponseT>() {
116+
@Override
117+
public void write(JsonWriter out, ResponseT value) {
118+
baseGson.toJson(value, responseType, out);
119+
}
120+
121+
@Override
122+
public ResponseT read(JsonReader in) {
123+
return baseGson.fromJson(in, responseType);
124+
}
125+
};
126+
responseMarshaller =
127+
new GsonBuilder().registerTypeAdapter(responseType, responseTypeAdapter).create();
128+
}
121129

122130
return new AutoValue_ApiMethodDescriptor<>(
123131
fullMethodName,
@@ -137,8 +145,9 @@ ResponseT parseResponse(Reader input) {
137145
return getResponseMarshaller().fromJson(input, getResponseType());
138146
}
139147

140-
void writeRequest(Appendable output, RequestT request) {
141-
this.getRequestMarshaller().toJson(request, output);
148+
@InternalApi
149+
public void writeResponse(Appendable output, Class clazz, Object response) {
150+
this.getResponseMarshaller().toJson(response, clazz, output);
142151
}
143152

144153
void writeRequestBody(RequestT apiMessage, Appendable output) {
@@ -188,7 +197,7 @@ public Builder<RequestT, ResponseT> setResourceNameField(String resourceNameFiel
188197
}
189198

190199
public Builder<RequestT, ResponseT> setQueryParams(Set<String> queryParams) {
191-
this.queryParams = queryParams;
200+
this.queryParams = ImmutableSet.copyOf(queryParams);
192201
return this;
193202
}
194203

gax-httpjson/src/main/java/com/google/api/gax/httpjson/HttpRequestRunnable.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import com.google.api.client.json.JsonObjectParser;
4141
import com.google.api.client.util.GenericData;
4242
import com.google.api.core.SettableApiFuture;
43+
import com.google.api.gax.rpc.ApiException;
4344
import com.google.api.pathtemplate.PathTemplate;
4445
import com.google.auth.http.HttpCredentialsAdapter;
4546
import com.google.auth.oauth2.GoogleCredentials;
@@ -131,6 +132,16 @@ public void run() {
131132

132133
HttpResponse httpResponse = httpRequest.execute();
133134

135+
if (methodDescriptor.getResponseType() == null) {
136+
if (!httpResponse.isSuccessStatusCode()) {
137+
throw new ApiException(
138+
null,
139+
HttpJsonStatusCode.of(httpResponse.getStatusCode(), httpResponse.getStatusMessage()),
140+
false);
141+
}
142+
responseFuture.set(null);
143+
return;
144+
}
134145
ResponseT response =
135146
methodDescriptor.parseResponse(new InputStreamReader(httpResponse.getContent()));
136147
responseFuture.set(response);

gax-httpjson/src/main/java/com/google/api/gax/httpjson/InstantiatingHttpJsonChannelProvider.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
*/
3030
package com.google.api.gax.httpjson;
3131

32+
import com.google.api.client.http.HttpTransport;
3233
import com.google.api.core.BetaApi;
3334
import com.google.api.core.InternalExtensionOnly;
3435
import com.google.api.gax.core.ExecutorProvider;
@@ -61,12 +62,25 @@ public final class InstantiatingHttpJsonChannelProvider implements TransportChan
6162
private final ExecutorProvider executorProvider;
6263
private final HeaderProvider headerProvider;
6364
private final String endpoint;
65+
private final HttpTransport httpTransport;
6466

6567
private InstantiatingHttpJsonChannelProvider(
6668
ExecutorProvider executorProvider, HeaderProvider headerProvider, String endpoint) {
6769
this.executorProvider = executorProvider;
6870
this.headerProvider = headerProvider;
6971
this.endpoint = endpoint;
72+
this.httpTransport = null;
73+
}
74+
75+
private InstantiatingHttpJsonChannelProvider(
76+
ExecutorProvider executorProvider,
77+
HeaderProvider headerProvider,
78+
String endpoint,
79+
HttpTransport httpTransport) {
80+
this.executorProvider = executorProvider;
81+
this.headerProvider = headerProvider;
82+
this.endpoint = endpoint;
83+
this.httpTransport = httpTransport;
7084
}
7185

7286
@Override
@@ -129,6 +143,7 @@ private TransportChannel createChannel() throws IOException {
129143
.setEndpoint(endpoint)
130144
.setHeaderEnhancers(headerEnhancers)
131145
.setExecutor(executor)
146+
.setHttpTransport(httpTransport)
132147
.build();
133148

134149
return HttpJsonTransportChannel.newBuilder().setManagedChannel(channel).build();
@@ -156,13 +171,15 @@ public static final class Builder {
156171
private ExecutorProvider executorProvider;
157172
private HeaderProvider headerProvider;
158173
private String endpoint;
174+
private HttpTransport httpTransport;
159175

160176
private Builder() {}
161177

162178
private Builder(InstantiatingHttpJsonChannelProvider provider) {
163179
this.executorProvider = provider.executorProvider;
164180
this.headerProvider = provider.headerProvider;
165181
this.endpoint = provider.endpoint;
182+
this.httpTransport = provider.httpTransport;
166183
}
167184

168185
/**
@@ -196,12 +213,19 @@ public Builder setEndpoint(String endpoint) {
196213
return this;
197214
}
198215

216+
/** Sets the HTTP transport to be used. */
217+
public Builder setHttpTransport(HttpTransport httpTransport) {
218+
this.httpTransport = httpTransport;
219+
return this;
220+
}
221+
199222
public String getEndpoint() {
200223
return endpoint;
201224
}
202225

203226
public InstantiatingHttpJsonChannelProvider build() {
204-
return new InstantiatingHttpJsonChannelProvider(executorProvider, headerProvider, endpoint);
227+
return new InstantiatingHttpJsonChannelProvider(
228+
executorProvider, headerProvider, endpoint, httpTransport);
205229
}
206230
}
207231
}

gax-httpjson/src/main/java/com/google/api/gax/httpjson/ManagedHttpJsonChannel.java

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.google.api.client.json.jackson2.JacksonFactory;
3636
import com.google.api.core.ApiFuture;
3737
import com.google.api.core.BetaApi;
38+
import com.google.api.core.InternalApi;
3839
import com.google.api.core.SettableApiFuture;
3940
import com.google.api.gax.core.BackgroundResource;
4041
import com.google.common.base.Preconditions;
@@ -72,24 +73,31 @@ private ManagedHttpJsonChannel(
7273
this.httpTransport = httpTransport == null ? new NetHttpTransport() : httpTransport;
7374
}
7475

76+
@InternalApi
77+
<ResponseT, RequestT> Runnable createRunnable(
78+
final HttpJsonCallOptions callOptions,
79+
final RequestT request,
80+
final ApiMethodDescriptor<RequestT, ResponseT> methodDescriptor,
81+
final SettableApiFuture<ResponseT> responseFuture) {
82+
return HttpRequestRunnable.<RequestT, ResponseT>newBuilder()
83+
.setApiFuture(responseFuture)
84+
.setApiMethodDescriptor(methodDescriptor)
85+
.setHeaderEnhancers(headerEnhancers)
86+
.setHttpJsonCallOptions(callOptions)
87+
.setHttpTransport(httpTransport)
88+
.setJsonFactory(jsonFactory)
89+
.setRequest(request)
90+
.setEndpoint(endpoint)
91+
.build();
92+
}
93+
7594
public <ResponseT, RequestT> ApiFuture<ResponseT> issueFutureUnaryCall(
7695
final HttpJsonCallOptions callOptions,
7796
final RequestT request,
7897
final ApiMethodDescriptor<RequestT, ResponseT> methodDescriptor) {
7998
final SettableApiFuture<ResponseT> responseFuture = SettableApiFuture.create();
80-
HttpRequestRunnable<RequestT, ResponseT> runnable =
81-
HttpRequestRunnable.<RequestT, ResponseT>newBuilder()
82-
.setApiFuture(responseFuture)
83-
.setApiMethodDescriptor(methodDescriptor)
84-
.setHeaderEnhancers(headerEnhancers)
85-
.setHttpJsonCallOptions(callOptions)
86-
.setHttpTransport(httpTransport)
87-
.setJsonFactory(jsonFactory)
88-
.setRequest(request)
89-
.setEndpoint(endpoint)
90-
.build();
91-
92-
executor.execute(runnable);
99+
100+
executor.execute(createRunnable(callOptions, request, methodDescriptor, responseFuture));
93101

94102
return responseFuture;
95103
}

0 commit comments

Comments
 (0)