Intercepting an assignment in Java - java

I'm using REST-Assured library with TestNG for receiving the response in a Response object as below.
Response response;
#Test
public void someTest() {
RestAssured.baseURI = "some_valid_baseURI";
RestAssured.basePath = "some_valid_endpoint";
response = RestAssured.given().contentType(ContentType.JSON).when().get();
}
I have several test methods like the above-mentioned method in a test class. Is there any way to intercept the response assignment so that I can, somewhere else (e.g. in a method annotated by an #AfterMethod), know that the method being used to get the response is the GET method?
PS: I did not find any in-built way in the REST-Assured library to do this.

The answer in Is it possible to extract the method name from the response object? serves my purpose for this question. Sorry about the generic question line here though!

Related

Mock an object which is not injected

I'm new to Java programming and I have the following code:
import javax.ws.rs.client.ClientBuilder;
public class Foo {
private final Client http;
Foo() {
http = ClientBuilder.newClient().register(CurlRequestFactory.getCurlRequestFactory().get(LOGGER, “someString”));
}
public someMethod() {
Invocation.Builder request = http.target(getURI(“someUri”)).request().header(“someHeader”, “someValue”);
Response response = request.get();
}
}
I want to write a unit test for someMethod() where request.get() would throw an exception. For this I require that request object should be set as a mock object.
But I'm unable to do so as it is being initialized directly instead of getting injected.
I know I can mock an object if it was getting injected as below:
Response responseMock = Mockito.mock(Response.class);
Mockito.when(responseMock.get()).thenThrow(new Exception("someMessage"));
But I couldn't find anything which works for my scenario.
PS: I don't want to use Powermock.
I have come across few things that Mokito does not support. One is this scenario. Either you have to change your code to inject it or use PowerMockito. I don't think there is any other option.
Your method is probably doing too many things. I imagine that you don't want to just return the Response from someMethod. Refactor your code to someMethod(Response response) or even better someMethod(Pojo responseBody) and then test that.
I don't know what your use case is, but someMethod probably belongs to another class (I'll call it Bar) separate from the http client class (Foo). You can then inject Foo into Bar and do the test. Is there any reason why you wouldn't want to refactor to that?

How to use retrofit without any pojo or data class or model class

I am working on an application where I want to use retrofit, but response from API is very large and can not be converted in any data class or POJO class, and also the response is dynamic it increase with user actions for backup, So I want to ask this a long time that is there any way where I can use retrofit without making response data class or POJO class otherwise I have to move back to basic Http way of using REST api's .
If anyone have achieved this or used before , please give some idea how to achieve this, would be a great help. Thanks in advance.
From retrofit docs:
[1] Retrofit is the class through which your API interfaces are turned into callable objects.
[2] Retrofit turns your HTTP API into a Java interface.
Sole purpose of Retrofit is to abstract your API calls as Java interfaces. IT was meant to be used with interfaces and POJOs, it is designed that way. If you don't want to use POJOs, you can use OkHttp which is actually used by Retrofit under the hood. Retrofit should only be used when you need an abstraction for your HTTP calls as Java objects.
You can always just send strings via the #Body annotation.
public interface YourService{
#POST("some/extension")
Call<Object> makeCall(#Body String body);
}
You can access the body of the response like this:
service.makeCall(yourCustomString).enqueue(new Callback<String>() {
#Override
public void onResponse(Response<String> response) {
String content = response.body(); // this gives the response body as a string
}
#Override
public void onFailure(Throwable t) {...}
});
I still think using JSON-Converters is the way to go. You might just need a lot of nested classes inside of the wrapping response/request classes depending on the JSON structure. The size beeing different doesn't matter and can easly be created using lists and optional attributes. How big do your responses get? Moshi for example doesn't really have a size limit.

Why isn't JSON being unmarshalled into my Java class?

I'm using Spring Boot and RestTemplate to GET data from an in-house service. The JSON I'm getting back as the response isn't being unmarshalled into my object and I'm unable to figure out why. (I'm consuming other similar REST APIs and those are working, so I've done this before.)
The code for making the request is standard stuff:
public ChecklistResponse getCurrentStatus(String studentId) {
RestTemplate restTemplate = createRestTemplate();
HttpHeaders httpHeaders = this.createHeaders();
String url = this.createItemStatusUrl(studentId);
ResponseEntity<ChecklistResponse> responseEntity = restTemplate.exchange(url, HttpMethod.GET,
new HttpEntity<>(httpHeaders), ChecklistResponse.class);
ChecklistResponse checklistResponse = responseEntity.getBody();
return checklistResponse;
}
The entire Object tree is large, so I can't really show it here. ChecklistResponse is simple enough, though:
public class ChecklistResponse {
private HttpStatus httpStatus;
private String responseType;
private Response response;
public ChecklistResponse() {
}
... getters/setters, equals, hashCode, toString ...
}
The start of the JSON response looks like this:
{
"httpStatus": {
"code": "200",
"description": "OK"
},
"responseType": "namespaceURI=\"http://bmeta.xxx.com/student/studentChecklistV0.xsd\" element=\"studentChecklist\"",
"response": {
"studentChecklist": {
"identifier": {
I set up interceptors to verify that I'm getting a response back. I ran it with the interceptors disabled, too, so that I know it's not consuming the response (though I'm using the interceptors successfully elsewhere and the object are properly unmarshalling.)
My question is, how can I debug this problem? I've tried enabling Jackson debugging, but that yields nothing. I've set breakpoints throughout the ChecklistResponse class, but it doesn't hit any of those.
Most likely you have forgot to add public parameterless constructor, add one like this:
public ChecklistResponse(){}
you should add these constructors to all classes in the object tree.
Another thing to look at is if the issue is a result of the values in the JSON object, ex, unescaped quotation etc .. try to make a unit test with a mocked object with trivial values but none empty/null ones and see if that test can pass or not, case sensitive issues sometimes cause this to fail as well, set break points in the getters/setters, these should be called in the process, make sure they are public as well as the classes themselves, final thing I can think of is the circular reference, make sure you don't have that as well in your object as this will cause issues.
Make sure that the model object ChecklistResponse correctly represents the map for the JSON object returned by the API you are testing with.

Defining Retrofit2 interface - Method without Response body

I am defining the Call objects in a Retrofit2 interface, to consume an external Rest API.
For most of the calls, we have something similar to :
#POST("/api/v1/methodEndPoint")
public Call<MethodResponse> methodName(#Body MethodRequest methodRequest);
However, my question is: How should I define a method if there is no Response object (a POST call, with no response body, we just mind about the status). Retrofit throws an exception if I just write the following:
#POST("/api/v1/methodEndPoint")
public Call methodName(#Body MethodRequest methodRequest);
Thanks for your help, have a nice day!
For defining a method without any response in Retrofit 2, the return type of method should be Void
You can try like :
#POST("/api/v1/methodEndPoint")
Call <Void> methodName(#Body MethodRequest methodRequest);
Use ResponseBody. Basically, you can do it like this:
#POST("/api/v1/methodEndPoint")
public Call<ResponseBody> methodName(#Body MethodRequest methodRequest);
You will have access to onResponse and onFailure callbacks however there will be no data deserialisation attempt

mock https request in java

Let's say I'm writing an application and I need to be able to do something like this:
String url = "https://someurl/";
GetMethod method = new GetMethod(URLEncoder.encode(url));
String content = method.getResponseBodyAsString();
Is there a way to provide a mock server that would let me handle the https request? What I'm looking for is a way to write unit tests, but I need to be able to mock the part that actually goes out to https://someurl so I can get a known response back.
Take a look at jadler (http://jadler.net), an http stubbing/mocking library I've been working on for some time. The 1.0.0 stable version has been just released, it should provide the capabilities you requested:
#Test
public void getAccount() {
onRequest()
.havingMethodEqualTo("GET")
.havingURIEqualTo("/accounts/1")
.havingBody(isEmptyOrNullString())
.havingHeaderEqualTo("Accept", "application/json")
.respond()
.withTimeout(2, SECONDS)
.withStatus(200)
.withBody("{\"account\":{\"id\" : 1}}")
.withEncoding(Charset.forName("UTF-8"))
.withContentType("application/json; charset=UTF-8");
final AccountService service = new AccountServiceRestImpl("http", "localhost", port());
final Account account = service.getAccount(1);
assertThat(account, is(notNullValue()));
assertThat(account.getId(), is(1));
}
#Test
public void deleteAccount() {
onRequest()
.havingMethodEqualTo("DELETE")
.havingPathEqualTo("/accounts/1")
.respond()
.withStatus(204);
final AccountService service = new AccountServiceRestImpl("http", "localhost", port());
service.deleteAccount(1);
verifyThatRequest()
.havingMethodEqualTo("DELETE")
.havingPathEqualTo("/accounts/1")
.receivedOnce();
}
You essentially have two options:
1. Abstract the call to the framework and test this.
E.g. refactor the code to allow you to inject a mock implementation at some point. There are many ways to do this. e.g. create a getUrlAsString() and mock that. (also suggested above). Or create a url getter factory that returns a GetMethod object. The factory then can be mocked.
2. Start up a app server as part of the test and then run your method against it. (This will be more of an integration test)
This can be achieved in an number of ways. This can be external to the test e.g. the maven jetty plugin. or the test can programmatically start up the server. see: http://docs.codehaus.org/display/JETTY/Embedding+Jetty
Running it over https will complicate this but it will still be possible with self signed certs. But I'd ask yourself - what exactly you want to test? I doubt you actually need to test https functionality, its a proven technology.
Personally I'd go for option 1 - you are attempting to test functionality of an external library. That is usually unnecessary. Also it's good practice to abstract out your dependencies to external libraries.
Hope this helps.
If you are writing a unit test, you dont want any external dependencies. from the api,
GetMethod
extends
HttpMethod
so you can easily mock it with your favorite mocking library. Your
method.getResponseBodyAsString()
call can be mocked to return any data you want.
You can wrap that code in some class and have WebClient.getUrl() and then mock (e.g. jmock) that method to return stored files - say
expectation {
oneOf("https://someurl/"), will(returnValue(someHTML));
}
Take a look at JWebUnit http://jwebunit.sourceforge.net/
Here is an example of a test...Its really quite intuitive.
public class ExampleWebTestCase extends WebTestCase {
public void setUp() {
super.setUp();
setBaseUrl("http://localhost:8080/test");
}
public void test1() {
beginAt("/home");
clickLink("login");
assertTitleEquals("Login");
setTextField("username", "test");
setTextField("password", "test123");
submit();
assertTitleEquals("Welcome, test!");
}
}
You could always launch a thttpd server as part of your unit test to serve the requests locally. Though, ideally, you have a well tested GetMethod, and then you can just mock it, and not have to actually have a remote server around for ALL of your tests.
Resources
thttpd: http://www.acme.com/software/thttpd/
To what extend are you interested in mocking this "Get" call, because if you are looking for a general purpose mocking framework for Java which integrates well with JUnit and allows to setup expectations which are automatically asserted when incorporated into a JUnit suite, then you really ought to take a look at jMock.
Now without more code, it's hard to determine whether this is actually what you are looking for, but a (somewhat useless) example, of something similar to the example code you wrote, would go something like this:
class GetMethodTest {
#Rule public JUnitRuleMockery context = new JunitRuleMockery();
#Test
public void testGetMethod() throws Exception {
// Setup mocked object with expectations
final GetMethod method = context.mock(GetMethod.class);
context.checking(new Expectations() {{
oneOf (method).getResponseBodyAsString();
will(returnValue("Response text goes here"));
}});
// Now do the checking against mocked object
String content = method.getResponseBodyAsString();
}
}
Use xml mimic stub server, that can simulate static http response based on request parameters, headers, etc. It is very simple to configure and use it.
http://xmlmimic.sourceforge.net/
http://sourceforge.net/projects/xmlmimic/

Categories