Google cloud function integration testing pass param? - java

I have created a cloud function to print greetings like "Hello David!". my function below:
public void service(HttpRequest request, HttpResponse response)
throws IOException {
String name = request.getFirstQueryParameter("name").orElse("world");
try {
JsonElement requestParsed = gson.fromJson(request.getReader(), JsonElement.class);
JsonObject requestJson = null;
if (requestParsed != null && requestParsed.isJsonObject()) {
requestJson = requestParsed.getAsJsonObject();
}
if (requestJson != null && requestJson.has("name")) {
name = requestJson.get("name").getAsString();
}
} catch (JsonParseException e) {
logger.severe("Error parsing JSON: " + e.getMessage());
}
var writer = new PrintWriter(response.getWriter());
writer.printf("Hello %s!", name);
}
I have written a integration test like below:
#BeforeEach
public void setUp() throws IOException {
String baseDir = System.getProperty("user.dir");
emulatorProcess = new ProcessBuilder()
.command("./../gradlew", "alo")
.directory(new File(baseDir))
.start();
}
#AfterEach
public void tearDown() throws IOException {
InputStream stdoutStream = emulatorProcess.getInputStream();
ByteArrayOutputStream stdoutBytes = new ByteArrayOutputStream();
stdoutBytes.write(stdoutStream.readNBytes(stdoutStream.available()));
System.out.println(stdoutBytes.toString(StandardCharsets.UTF_8));
if (emulatorProcess.isAlive()) {
emulatorProcess.destroy();
}
}
#Test
void helloHttp_shouldRunWithFunctionsFramework() throws Throwable {
String functionUrl = BASE_URL + "/helloHttp";
HttpRequest getRequest = HttpRequest.newBuilder().uri(URI.create(functionUrl)).GET().build();
RetryRegistry registry = RetryRegistry.of(RetryConfig.custom()
.maxAttempts(6)
.intervalFunction(IntervalFunction.ofExponentialBackoff(200, 2))
.retryExceptions(IOException.class)
.retryOnResult(body -> body.toString().length() == 0)
.build());
Retry retry = registry.retry("my");
String body = Retry.decorateCheckedSupplier(retry, () -> client.send(
getRequest,
HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)).body()
).apply();
assertThat(body).isEqualTo("Hello world!");
}
So I want to fake a params name in the integration test to pass to my GCP function.
so in my GCP function I can take it like this: name = requestJson.get("name").getAsString();. How do I do it?

I just search it out and the answer is: add post method like this
HttpRequest getRequest = HttpRequest
.newBuilder()
.uri(URI.create(functionUrl))
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString("{\"name\":\"David\"}"))
.build();

Related

How I can test that an OkHttpCall is performed with specific headers?

I have the following class:
class MyClass {
private OkHttpClient httpClient;
private String session_id;
public MyClass() {
this.setHttpClient(new OkHttpClient());
}
public String getSessionId() {
return session_id;
}
public void setHttpClient(OkHttpClient httpClient) {
this.htttpClient = httpClient;
}
public String retrieveUrlContents(String url, String csrfToken) throws Exception {
url = this.url.replaceAll("/$", "") + "/" + url.replaceAll("^/", "");
csrfToken = (csrfToken == null) ? "" : csrfToken;
if (!csrfToken.equals("")) {
long unixtime = System.currentTimeMillis() / 1000L;
// AJAX Calls also require to offer the _ with a unix timestamp alongside csrf token
url += "?_=" + unixtime + "&csrf_token=" + csrfToken;
}
Request.Builder request = new Request.Builder()
.url(url)
.header("User-Agent", "Mozila/5.0 (X11;Ubuntu; Linux x86_64; rv:87.0) Gecko/20100101 Firefox/87.0");
String session_id = this.getSessionId();
session_id = session_id == null ? "" : session_id;
if (!session_id.equals("")) {
request.header("Set-Cookie", "session_id=" + session_id + ";login_uid=" + Math.random());
}
Response response = this.httpClient.newCall(request.build()).execute();
int code = response.code();
if (code != 200) {
throw new Exception("The url " + url + " returned code " + code);
}
String responseBody = response.body().string();
return responseBody;
}
}
And I want to unit-test the case that if getSessionId actually return a non-null or a non-empty string then the httpCall is performed:
class MyClassTest {
private static OkHttpClient mockHttpClient(final String serializedBody, final boolean json, int code) throws IOException {
final OkHttpClient okHttpClient = mock(OkHttpClient.class);
final Call remoteCall = mock(Call.class);
code = code < 0 ? 200 : code;
final Response response = new Response.Builder()
.request(new Request.Builder().url("http://url.com").build())
.protocol(Protocol.HTTP_1_1)
.code(code).message("").body(
ResponseBody.create(
MediaType.parse(json ? "application/json" : "text/html"),
serializedBody
))
.build();
when(remoteCall.execute()).thenReturn(response);
when(okHttpClient.newCall(any())).thenReturn(remoteCall);
return okHttpClient;
}
#Test
public void retrieveUrlContentsIsRetrievedWithSessionId() {
File file = (new File("src/test/resources/csrfInvalid.html")).getAbsoluteFile();
String path = file.getPath();
Scanner fileReader = new Scanner(file);
String contents = fileReader.useDelimiter("\\Z").next();
OkHttpClient client = this.mockHttpClient(contents, false, 200);
final Η300sCredentialsRetriever retriever = spy(Η300sCredentialsRetriever.class);
doReturn("Hello").when(retriever).getSessionId();
retriever.setUrl("192.168.2.1");
retriever.setHttpClient(client);
String response = retriever.retrieveUrlContents("/example.html");
// Test that http call is permormed with SessionId
// Rest of Assertions
}
}
What I want is to Assert that OkHttp3 is performing an HttpCall with the appropriate Cookie Header. But I do not know how I can assert that the HttpCall is performed with this header. Do you have any ideas how I can test that?
One option is MockWebServer, look at RecordedRequest which can confirm the headers you sent.
https://github.com/square/okhttp/tree/master/mockwebserver
https://www.baeldung.com/spring-mocking-webclient#mockwebserverchecking
RecordedRequest request1 = server.takeRequest();
assertEquals("/v1/chat/messages/", request1.getPath());
assertNotNull(request1.getHeader("Authorization"));

Unit test a private method via a protected method in Java

I've these two methods from my MetadataManagement class which I'd like to unit test:
#Override
protected void doPut(final HttpServletRequest request, final HttpServletResponse response,
final MetadataResource resource)
throws IOException {
ServiceCommon.checkRole(getSubject(request));
if (resource.getType() != Type.CONTAINER) {
final String err = "Request not allowed for " + request.getURI();
throw new ServiceApiException(ServiceApiError.METHOD_NOT_ALLOWED, err);
}
final String name = getContainerName(resource);
final ServiceApiMetadata config = getConfig(request, PATH);
final StorageLocation storageLocation = getStorageLocation(conf.getStorageLocation());
if (config.getNotifications() != null) {
checkMethodSupported(id);
checkService(id);
}
}
private ServiceApiMetadata getConfig(final HttpServletRequest request, final String path)
throws IOException {
final Schema schema;
try (final InputStream inStream = this.getClass().getResourceAsStream(path)) {
final JSONObject origSchema = new JSONObject(new JSONTokener(inStream));
if (isGoldStar()) {
origSchema.getJSONObject("properties")
.getJSONObject("notifications")
.getJSONObject("properties")
.getJSONObject("topic")
.put("pattern", "^[0-9A-Za-z-.]*$");
}
schema = SchemaLoader.load(origSchema);
}
final ServiceApiMetadata config;
try (final BufferedReader reader = request.getReader()) {
final JSONObject json = new JSONObject(new JSONTokener(reader));
schema.validate(json);
config = ServiceApiMetadata.read(json);
} catch (final ValidationException e) {
_logger.debug(e.getMessage());
if (e.getLocation().contains("#/properties/notifications")) {
throw new ServiceApiException(ServiceApiError.MALFORMED_NOTIFICATIONS_ERROR,
ServiceApiErrorMessage.MALFORMED_JSON);
} else {
throw new ServiceApiException(ServiceApiError.MALFORMED_JSON);
}
} catch (final JSONException e) {
_logger.debug(e.getMessage());
throw new ServiceApiException(ServiceApiError.MALFORMED_JSON);
}
return config;
}
As I understand it I can not directly call getConfig in my test because the method is private. I believe using reflection is an option but is not advised. Based on that, any test of getConfig should be done through doPut.
What I'm most interested in checking is if getConfig.isGoldStar is true, the origSchema pattern updates to ^[0-9A-Za-z]*$ and if it is false it remains at ^[0-9A-Za-z-._]*$.
To call doPut in my test I will need HttpServletRequest, HttpServletResponse and MetadataResource objects. I'm not sure how I generate these. HttpServletRequest and HttpServletResponse are from javax.servlet.ServletRequest and MetadataResource comes from within my project. It takes HttpServletRequest and an enum as parameters.
How do I do this test? I think I should be OK once I can call the doPut method but I'm struggling to do that.

Wiremock: HTTP Web Site Testing without UI

I"m given a requirement on how to test HTTP website without UI. Let says, we have a google website search functionalities (Not Web Services) and I need to test it. How to start? Can anyone give some example (JUnit)(Get/Post Method) for me to start this project. I tried reading the official documentation but found nothing about it. Thanks in advance.
You can do it with the following snippet
public class Searcher {
public String search(String searchUrl, String searchWord) throws IOException, URISyntaxException {
try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
URIBuilder builder = new URIBuilder(searchUrl);
builder.setParameter("search_term", searchWord);
HttpGet request = new HttpGet(builder.build());
HttpResponse httpResponse = httpClient.execute(request);
return convertResponseToString(httpResponse);
}
}
private String convertResponseToString(HttpResponse response) throws IOException {
try (Scanner scanner = new Scanner(response.getEntity().getContent(), "UTF-8")) {
String responseString = scanner.useDelimiter("\\Z").next();
return responseString;
}
}
}
public class SearcherTest {
#Rule
public WireMockRule wireMockRule = new WireMockRule(options().dynamicPort());
#Test
public void searchTest() throws IOException, URISyntaxException {
String searchWord = "something";
String expectedResult = "Your expected result";
stubFor(get(urlPathEqualTo("/search"))
.withQueryParam("search_term", equalTo(searchWord))
.willReturn(aResponse()
.withBody(expectedResult)));
Searcher searcher = new Searcher();
String searchResult = searcher.search("http://localhost:" + wireMockRule.port() + "/search", searchWord);
verify(getRequestedFor(urlPathEqualTo("/search"))
.withQueryParam("search_term", equalTo(searchWord)));
assertEquals(expectedResult, searchResult);
}
}

Mockito JUnit Testing POST files

I am struggling to write test(s) for the following post method (junit/mockito)
POST method
public JSONObject post(final String url, final Map<String, File> fileMap) {
final OkHttpClient client = OkHttpClientSingleton.getInstance();
final MultipartBody.Builder builder = new MultipartBody.Builder()
.setType(MultipartBody.FORM);
try {
for (final Map.Entry entry : fileMap.entrySet()) {
final String contentType;
final Path path = Paths.get(((File) entry.getValue()).getAbsolutePath());
contentType = Files.probeContentType(path);
final MediaType FILE_MEDIA_TYPE = MediaType.parse(contentType);
builder.addFormDataPart((String) entry.getKey(), ((File) entry.getValue()).getName(), RequestBody.create(FILE_MEDIA_TYPE, (File) entry.getValue()));
}
} catch (final IOException e) {
e.printStackTrace();
return null;
}
final RequestBody requestBody = builder.build();
final Request request = new Request.Builder()
.url(url)
.post(requestBody)
.build();
return execute(client, request);
}
and the execute method looks like:
private JSONObject execute(final OkHttpClient client, final Request request) {
try {
final Response response = client.newCall(request).execute();
final String str = Objects.requireNonNull(response.body()).string();
return new JSONObject(str);
} catch (final IOException e) {
e.printStackTrace();
}
return buildErrorResponse("Unable to execute request");
}
I have no "fields" to create mocks for (my usual MO!), any tips muchappreciated. I can force an error easily enough but to test full flow at least until the POST
You can mock the web application that receives the post and verify that the correct data is send. E.g. you can use http://mock-server.com for this.

HttpServletRequest.getParamter() return null in CXF Restful service(Post)

I wrote a Web API using Apache CXF. When I use HttpServletRequest.getParamter() in a post method, it return null.Here is the code:
#Path("/")
public class TokenService extends DigiwinBaseService {
private static void printRequest(HttpServletRequest httpRequest) {
System.out.println("\n\n Headers");
Enumeration headerNames = httpRequest.getHeaderNames();
while (headerNames.hasMoreElements()) {
String headerName = (String) headerNames.nextElement();
System.out.println(headerName + " = " + httpRequest.getHeader(headerName));
}
System.out.println("\n\n Parameters");
Enumeration params = httpRequest.getParameterNames();
while (params.hasMoreElements()) {
String paramName = (String) params.nextElement();
System.out.println(paramName + " = " + httpRequest.getParameter(paramName));
}
System.out.println("\n\n Row data");
System.out.println(extractPostRequestBody(httpRequest));
}
private static String extractPostRequestBody(HttpServletRequest request) {
if ("POST".equalsIgnoreCase(request.getMethod())) {
Scanner s = null;
try {
s = new Scanner(request.getInputStream(), "UTF-8").useDelimiter("\\A");
} catch (IOException e) {
e.printStackTrace();
}
return s.hasNext() ? s.next() : "null";
}
return "null";
}
#POST
#Consumes("application/x-www-form-urlencoded")
public Response Authorize(#FormParam("param") String param,
#FormParam("param2") String param2,#Context HttpServletRequest httpRequest) throws OAuthSystemException {
printRequest(httpRequest);
System.out.println("param:"+param);
System.out.println("param2:"+param2);
return Response.status(HttpServletResponse.SC_OK).entity("OK").build();
}
}
Here is the test code
public class HttpClientTest {
public static void main(String[] args) throws Exception{
String url4 = "/api/services/Test";
String host = "127.0.0.1";
HttpClient httpClient = new HttpClient();
httpClient.getHostConfiguration().setHost(host, 8080, "http");
HttpMethod method = postMethod(url4);
httpClient.executeMethod(method);
String response = method.getResponseBodyAsString();
System.out.println(response);
}
private static HttpMethod postMethod(String url) throws IOException{
PostMethod post = new PostMethod(url);
post.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=gbk");
NameValuePair[] param = {
new NameValuePair("param","param1"),
new NameValuePair("param2","param2"),} ;
post.setRequestBody(param);
post.releaseConnection();
return post;
}
}
Here is the print out :
Headers
content-type = application/x-www-form-urlencoded;charset=gbk
user-agent = Jakarta Commons-HttpClient/3.1
host = 127.0.0.1:8080
content-length = 26
Parameters
Row data
null
param:param1
param2:param2
Why the Parameters is null? How can i get post params using HttpServletRequest.getParamter()
CXF is consuming the POST data to fill the FormParams.
https://issues.apache.org/jira/browse/CXF-2993
The resolution is "won't fix". In the issue, they suggest to use a MultivaluedMap to recover all params, or use only the HttpServletRequest
Option 1
#POST
#Consumes("application/x-www-form-urlencoded")
public Response Authorize( MultivaluedMap<String, String> parameterMap, #Context HttpServletRequest httpRequest) throws OAuthSystemException {
//parameterMap has your POST parameters
Option 2
#POST
#Consumes("application/x-www-form-urlencoded")
public Response Authorize( #Context HttpServletRequest httpRequest) throws OAuthSystemException {
//httpRequest.getParameterMap() has your POST parameters

Categories