How do you test multiple REST Requests? - java

//1) Request
//Given
String req = new ObjectMapper().writeValueAsString(new Request("2016-11-15"));
//set HttpHeaders
//set HttpEntity
// When
ResponseEntity responseEntity = restTemplate.exchange(url, HttpMethod.POST, httpEntity, String.class);
Is there a convenient way of unit testing multiple REST API requests? I would like to create a bunch of requests to submit to a queue which will then be processed. The request are to have different HttpHeaders and different ReportRequestBody.
I have done single request unit testing and are able to capture statuses using ResponseEntity.
Can anyone point me to some examples or documentation on best practices. I am a beginner and I am not sure where to start with multiple requests.

For testing requests and responses in DjangoRest you can use following tools or ways....
You can use print statement to see what is being printed and then you can interpret print results accordingly.
You can use Debugger of any IDE such as PyCharm.
You can use Postman to test your API as it gives you whole idea of
the responses you are getting.
For more information on requests you can visit here

Yes I would certainly say this is more of an integration/load test scenario. You may want to look into using Jmeter with Junit tests. You can use its JUnit Request Sampler. Here was a post on stackoverflow to a different question, but it provides a link to a helpful article. The post was Spring load testing . Here is also a link to the article directly https://www.blazemeter.com/blog/how-use-junit-jmeter. This should get you heading in the right direction.

Related

How to (unit) test method sending http request to MS Teams channel?

I've written a monitoring service class performing a database check for entries of a certain (considered erroneous) state. Based on the result of the database query, the service will send a notification to a Microsoft Teams channel using its Connector/Webhook functionality. It works all fine so far, but I can't wrap my head around how to properly test the respective methods. It's mainly the method sending the notification to Teams I'm struggling with:
public HttpStatus sendNotificationToTeams(MsTeamsCard card) throws JsonProcessingException {
HttpHeaders headers = new HttpHeaders();
ObjectWriter writer = new ObjectMapper().writer();
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(WebConfig.PROXY_HOST, WebConfig.PROXY_PORT));
SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
// Setup RestTemplate. Proxy is required, otherwise request returns HTTP 500 with misleading error message (array index out of bounds)
requestFactory.setProxy(proxy);
RestTemplate restTemplate = new RestTemplate(requestFactory);
// HTTP request incl. setup
headers.setContentType(MediaType.APPLICATION_JSON);
HttpEntity<String> request = new HttpEntity<>(writer.writeValueAsString(card), headers);
ResponseEntity<String> response = restTemplate.exchange(this.webhookUrl, HttpMethod.POST, request, String.class);
return response.getStatusCode();
}
I think I should definitely test this method since it's not trivial at all. However, there's not much that I think could reasonalby fail inside this method that is related to its particular arrangement of code - of course there may be problems, but things like network issues are out of scope of (unit) tests for this method. So how would I test this method reliably? I'm asking more from a general testing point of view (which is where I really lack knowledge) than requesting concrete help with a test framework or something (JUnit 4 is used btw). For example, one point is that I can't check the results of the HTTP call even if I mock it, because it requires a specific answer from Teams: the request might be successful but something could be wrong with Teams, and I can't really mock that. But maybe I'm just thinking too complicated here.
If you are looking for unit-testing your http-connector, you can do it with Wiremock. Check out this tutorial
For instance
#Test
public void shouldSendNotification() {
String path = "/endpoint";
wiremock.stubFor(get(urlEqualTo(path))
.willReturn(aResponse()
.withStatus(200))
);
HttpStatus status = sendNotificationToTeams(...);
assertThat(status).isEqualTo(200);
}

RestTemplate Test w specific parameters for REST Controller

I am writing Integration Tests for controllers using RestTemplate, so far I have been able to call most , however haven't been able to tackle this particular parameter combination.
I know how to deal with headers, GET or PUT parameters, but multiple String is sole one that have yet to figure. Dunno if #Annotations make difference.
#RequestMapping(value="/getBook", method = GET)
#ResponseStatus(OK)
public #ResponseBody
GetBookResponse getBook(#RequestParam("isbnID") String isbnID, #RequestParam(required=false) Double price, #RequestHeader(required=false) String publisher)
{
.....
}
and how this would work in the case for POST
Normally I use ResponseEntity to get response but been stuck pn how to prep it.
Typically we create a new HttpRequest and add the request parameters to it and submit your HttpRequest with all its corresponding parameters in your post. I don't know how to implement it with the framework you are using though. I've written tests for controllers and this is how I did it. GET request usually has just one parameter in the url so you don't really have to add request parameters but POST should have request parameters set to the httpRequest.

Jersey client testing

I have a Jersey client which performs post request to some black box service.
Also I have POJO mapping feature enabled.
I have integration tests already, they are calling real black box service.
Now I need to test my application without calling real black box service.
My question is: how can I test this Jersey client? I mean: how can I test Jersey client without calling real black box service?Maybe there is some possibility to mock JSON response in tests?
Environment: jersey-client and jersey-json versions - 1.19.1.
You can log the request using LoggingFilter to make sure your requests are according to your estimate. For running your test, you can use http://mockable.io/.
P.S. Do not forget to replace the Webtarget URL with MockableIO's URL.
You can try Karate which has recently introduced a way to create simple mocks for JSON responses. Here is an example:
https://gist.github.com/ptrthomas/35ef9d40623cbeade7388b2cbb29a3b1
While the above example is a "smart" mock, it is very easy to create hard-coded mocks, here is an example: https://github.com/intuit/karate/blob/master/karate-netty/src/test/java/com/intuit/karate/mock/_mock.feature
You can easily read files from JSON by using the read keyword.
I have performed an investigation concerning my question. Mentioned investigation resulted in such facts:
I haven't found features/mechanisms/etc. to test Jersey client without real calls to the server (in my case - black box service).
Jersey test framework provides features for testing Jersey server, but there are no features for testing Jersey client
The only one solution for testing client without server is to refactor my code in following way: split logic into two phazes. First phaze: get JSON response using Jersey. Second phaze: get JSON response (which we get in first phaze) and transform it into desired object. In general you'll have next code as a result:
Class< String > jsonResposeClass = String.class;
String jsonResponse = post( yourRequest, jsonResposeClass );
ObjectMapper mapper = new ObjectMapper();
YourResponseBean bean = mapper.readValue( jsonResponse , responseClass );
The solution above will give you a possibility to use mocking libraries like Mockito and mock method which performs post request.
If you have found any other solution/feature/special mechanism/etc which can also help in such kind of situation - please share :)

Provide the actual HTTP GET request within the response

I would like to provide the actual get request in a response. I am free to choose between placing that information into the header or the body of the response.
The current project setup includes:
Nginx as reverse proxy
Spring boot application
which are potential candidates to put in that logic.
Request:
GET http://localhost/api/users/2/photos/2
Response:
BODY {"some": "values",
"_request": "GET http://localhost/api/users/2/photos/2"}
or
HEADERS "custom-header-get-request": "GET http://localhost/api/users/2/photos/2"
BODY {"some": "values"}
I can easily add the information to the response of each Responseobject within the Controllers of the spring boot application. This approach is quite cumbersome, as it leads to a lot of codechanges and allways needs to be in mind that each Controller should take care of providing the requestinformation to the response, achieving the first solution.
Which other options do i have?

Jersey web service proxy

I am trying to implement a web service that proxies another service that I want to hide from external users of the API. Basically I want to play the middle man to have ability to add functionality to the hidden api which is solr.
I have to following code:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection,
#Context Request request) {
//extract URL params
//update URL to target internal web service
//put body from incoming request to outgoing request
//send request and relay response back to original requestor
}
I know that I need to rewrite the URL to point to the internally available service adding the parameters coming from either the URL or the body.
This is where I am confused how can I access the original request body and pass it to the internal web service without having to unmarshall the content? Request object does not seem to give me the methods to performs those actions.
I am looking for Objects I should be using with potential methods that would help me. I would also like to get some documentation if someone knows any I have not really found anything targeting similar or portable behaviour.
Per section 4.2.4 of the JSR-311 spec, all JAX-RS implementations must provide access to the request body as byte[], String, or InputStream.
You can use UriInfo to get information on the query parameters. It would look something like this:
#POST
#Path("/update/{collection}")
public Response update(#PathParam("collection") String collection, #Context UriInfo info, InputStream inputStream)
{
String fullPath = info.getAbsolutePath().toASCIIString();
System.out.println("full request path: " + fullPath);
// query params are also available from a map. query params can be repeated,
// so the Map values are actually Lists. getFirst is a convenience method
// to get the value of the first occurrence of a given query param
String foo = info.getQueryParameters().getFirst("bar");
// do the rewrite...
String newURL = SomeOtherClass.rewrite(fullPath);
// the InputStream will have the body of the request. use your favorite
// HTTP client to make the request to Solr.
String solrResponse = SomeHttpLibrary.post(newURL, inputStream);
// send the response back to the client
return Response.ok(solrResponse).build();
One other thought. It looks like you're simply rewriting the requests and passing through to Solr. There are a few others ways that you could do this.
If you happen to have a web server in front of your Java app server or Servlet container, you could potentially accomplish your task without writing any Java code. Unless the rewrite conditions were extremely complex, my personal preference would be to try doing this with Apache mod_proxy and mod_rewrite.
There are also libraries for Java available that will rewrite URLs after they hit the app server but before they reach your code. For instance, https://code.google.com/p/urlrewritefilter/. With something like that, you'd only need to write a very simple method that invoked Solr because the URL would be rewritten before it hits your REST resource. For the record, I haven't actually tried using that particular library with Jersey.
1/ for the question of the gateway taht will hide the database or index, I would rather use and endpoint that is configured with #Path({regex}) (instead of rebuilding a regexp analyser in your endpoint) .
Use this regex directly in the #path, this is a good practice.
Please take a look at another post that is close to this : #Path and regular expression (Jersey/REST)
for exemple you can have regexp like this one :
#Path("/user/{name : [a-zA-Z][a-zA-Z_0-9]}")
2/ Second point in order to process all the request from one endpoint, you will need to have a dynamic parameter. I would use a MultivaluedMap that gives you the possibility to add params to the request without modifying your endpoint :
#POST
#Path("/search")
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
#Produces({"application/json"})
public Response search( MultivaluedMap<String, String> params ) {
// perform search operations
return search( params);
}
3/ My 3rd advice is Reuse : make economy and economy make fewer bugs.
it's such a pitty to rewrite a rest api in order to perform solr search. You can hide the params and the endpoint, but could be great to keep the solr uri Rest formatting of the params in order to reuse all the search logic of solr directly in your api. This will make you perform a great economy in code even if you hide your solr instance behind you REST GATEWAY SERVER.
in this case you can imagine :
1. receive a query in search gateway endpoint
2. Transform the query to add your params, controls...
3. execute the REST query on solr (behind your gateway).

Categories