ClassCastException in Mockito - java

I have the following method for which I'm trying to write unit test using Mockito. I'm fairly new to Mockito and trying to catch up.
Method to test
public synchronized String executeReadRequest(String url) throws Exception{
String result = null;
RestClient client = null;
Resource res = null;
logger.debug("Start executing GET request on "+url);
try{
client = getClient();
res = client.resource(url);
result = res.contentType(this.requestType).accept(this.responseType).get(String.class);
}
catch(Exception ioe){
throw new Exception(ioe.getMessage());
}
finally{
res = null;
client = null;
}
logger.info("GET request execution is over with result : "+result);
return result;
}
The unit test with Mockito
#Test
public void testRestHandler() throws Exception {
RestHandler handler = spy(new RestHandler());
RestClient mockClient = Mockito.mock(RestClient.class,Mockito.RETURNS_DEEP_STUBS);
Resource mockResource = Mockito.mock(Resource.class,Mockito.RETURNS_DEEP_STUBS);
doReturn(mockClient).when(handler).getClient();
Mockito.when(mockClient.resource(Mockito.anyString())).thenReturn(mockResource);
//ClassCastException at the below line
Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");
handler.setRequestType(MediaType.APPLICATION_FORM_URLENCODED);
handler.setResponseType(MediaType.APPLICATION_JSON);
handler.executeReadRequest("abc");
}
But I'm getting a ClassCastException at the line
Mockito.when(mockResource.contentType(Mockito.anyString()).accept(Mockito.anyString()).get(Mockito.eq(String.class))).thenReturn("dummy read result");
Exception
java.lang.ClassCastException: org.mockito.internal.creation.jmock.ClassImposterizer$ClassWithSuperclassToWorkAroundCglibBug$$EnhancerByMockitoWithCGLIB$$4b441c4d cannot be cast to java.lang.String
Appreciate any help to resolve this.
Many thanks.

This style of chaining during stubbing isn't correct:
Mockito.when(
mockResource.contentType(Mockito.anyString())
.accept(Mockito.anyString())
.get(Mockito.eq(String.class)))
.thenReturn("dummy read result");
Even though you've set the mocks to return deep stubs, Matchers work via side-effects, so this line doesn't achieve what you think it does. All three matchers (anyString, anyString, eq) are evaluated during the call to when, and the way you have it your code is likely to throw InvalidUseOfMatchersException at the slightest provocation—including adding unrelated code or verifications later.
This means your problem isn't the use of eq(String.class): It's that Mockito is trying to work the Class matcher in where it doesn't belong.
Instead, you'll need to stub specifically:
Mockito.when(mockResource.contentType(Mockito.anyString()))
.thenReturn(mockResource);
Mockito.when(mockResource.accept(Mockito.anyString()))
.thenReturn(mockResource);
Mockito.when(mockResource.get(Mockito.eq(String.class))) // or any(Class.class)
.thenReturn("dummy read response");
Note that some of the difficulty here is that Apache Wink uses the Builder pattern, which can be laborious in Mockito. (I've returned mockResource here, but you could imagine returning specific other Resource objects, at the expense of requiring them in exactly that order later.) A better way might be to use a default Answer that returns this whenever possible.

Solved it by changing the get call to
get(Mockito.any(Class.class))

Related

JUnit and Mockito unit test for stream.mark(stream.available) when doing S3 putObject

I have a method which puts InputStream in s3 bucket.
#Override
public String putObject(#NonNull String s3BucketName, #NonNull String s3Key, #NonNull String content,
#NonNull ObjectMetadata metadataRequest) {
InputStream stream = new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8));
try {
stream.mark(stream.available());
} catch (IOException e) {
String errorMessage = String.format("Runtime error while marking stream.",
s3BucketName, s3Key);
throw new RuntimeException(errorMessage, e);
}
PutObjectRequest request = new PutObjectRequest(s3BucketName, s3Key, stream, metadataRequest);
return putObject(request);
}
I want to make the method cause IOException and then throw RuntimeException and I have written the unit test for the same.
#Test
public void putObjectTest_withStringContent_withMetadataRequest_IOError() {
ObjectMetadata metadataRequest = new ObjectMetadata();
metadataRequest.addUserMetadata(TEST_METADATA_KEY, TEST_METADATA_VALUE);
InputStream mockStream = Mockito.mock(InputStream.class);
Mockito.when(mockStream.mark(mockStream.available())).thenThrow(IOException.class);
assertThrows(RuntimeException.class, () -> s3Accessor.putObject
(TEST_S3BUCKET, TEST_S3OBJECT, TEST_STRING, metadataRequest));
}
This is what I have tried but this is showing error in editor
Required type:
T
Provided:
void
reason: no instance(s) of type variable(s) T exist so that void conforms to T
How can I make the method throw IOException?
stream.mark(...) will never throw any checked exceptions anyway so this is rather pointless.
You also don't need to mark or reset the stream manually at all. The SDK does that behind the scenes.
By default, the AWS SDK for Java attempts to retry failed transfers by marking the input stream before the start of a transfer and then resetting it before retrying.
If your stream is larger than 128 KB, then you may need to call setReadLimit to 1 byte greater than the size of the stream to avoid a ResetException when not using a FileInputStream. If it isn't, then you don't need to do anything. Regardless, you don't need to mark or reset the stream yourself.
However, for reference purposes, Mockito.when(...).thenThrow(...) is for method invocations that return a value.
stream.mark(mockStream.available()) is a method invocation that does not return a value (void return type).
As per docs:
Use doThrow() when you want to stub the void method with an exception.
In this case, replace:
Mockito.when(mockStream.mark(mockStream.available())).thenThrow(IOException.class);
With:
doThrow(IOException.class).when(mockStream).mark(mockStream.available());
stream is a ByteArrayInputStream. That will never ever ever throw any exception when mark is called. The documentation clearly states that no IOException can be thrown, and that the argument is ignored.
The exception doesn't come from the mark call, it comes from the available call. As the argument is ignored, just replace it with 0, and you don't need to catch the IOException. In fact, you'll get a compiler error:
exception java.io.IOException is never thrown in body of corresponding try statement

Rest Assured Framework complete JSON response matching

I am using Rest Assured Framework for API testing(Using Java).
At line (1),I am expecting error as there is mismatch in expected JSON response and Actual JSON response
But instead my code is executing successfully.
Can someone please tell me if I am doing anything wrong in below code?
public void test123() {
try {
//Read the Curl Request Input file
String json = input.readFromTextFile(
System.getProperty("user.dir") + "\\src\\test\\resources\\inputFile\\CurlDataFile.txt");
json = json.replaceAll(" ", "");
RestAssured.baseURI = "My URL";
given().
contentType("application/json").
body(json).
when().
post("").
then().
assertThat().body(matchesJsonSchemaInClasspath("testCurlOuput1.json")); (1)
} catch (IOException e) {
e.printStackTrace();
}catch(JsonSchemaValidationException e){
e.printStackTrace();
}
}
This is not directly relevant to REST-assured, but I suggest you take a look at Karate, because IMO it may be exactly what you are looking for.
One of the core features of Karate is that you can perform a full equality match of a JSON payload in one step.
And you can easily use JSON from files, which encourages the re-use of payloads across multiple tests.
You are catching all Exceptions. When your assertThat(..) fails, it throws an Exception. Put a breakpoint on the e.printStackTrace(); run in DEBUG mode and check that your AssertionException/Error isn't being caught.
Instead of catching exceptions, just add all Checked Exceptions to your test signature. If an exception is uncaught, it will fail the test. Alternatively, but less prefered in my opinion, resolve by putting fail(); in the catch block.
Finally I choose different library i.e. jayway.restassured library and then JSON Assert library (org.skyscreamer.jsonassert.JSONAssert) which will comapre actual and expected response.
public void test123() {
String postData = input.readFromTextFile(System.getProperty("user.dir") + "\\src\\test\\resources\\inputFile\\CurlDataFile.txt");
RestAssured.baseURI = "MY URL";
Response r = (Response)given().contentType("application/json").body(postData).when().post("");
String responseBody = r.getBody().asString();
String curlResponse = //I am providing expected Curl response here
//JSON Assertion for matching Expected and Actual response
JSONAssert.assertEquals(curlResponse, responseBody, false);
}
Also sometime we may want to avoid comparing particular field from JSON like some ID field which generate dynamically which we can do using JSON comparator
I am a fan of JSONAssert as this provides easy comparing of complete JSONs.
Just use .extract().response().getBody().asString() to get the string representation of the answer.
Complete example:
#Test
public void getReturnsExpectedDataForMailExampleCom() throws JSONException {
String response = get("/users/mail#example.com")
.then()
.statusCode(200)
.extract().response().getBody().asString();
JSONAssert.assertEquals(
"{\"email\":\"mail#example.com\",\"locale\":\"de-DE\"}",
response,
false);
}
Update The drawback is that the complete JSON is not output to stdout if the assertion fails.

Android okHttp Retry policy

I am trying to create a simple wrapper which will call the server download the information and parse the binary data sent .
for the connection I am using the library called okhttp , since the connection on 3G is not very reliable I have decided to implement a very simple re-try functionality using the following function**(Note this method will be always called from a background thread)**
private InputStream callServer() throws ServerException, NoNetworkAvailableException, ConnectionErrorException {
NetworkOperation networkOperation = getNetworkOperation();
InputStream inputStream = null;
//in case of network problems we will retry 3 times separated by 5 seconds before gave up
while (connectionFailedRetryCounter < connectionFailedMaximumAllowedRetries()) {
connectionFailedRetryCounter++;
try {
inputStream = networkOperation.execute();
break;//if this line was reached it means a successfull operation, no need to retry .
} catch (ConnectionErrorException e) {
if (canRetryToConnect()) {
Utils.forceSleepThread(Constants.Communications.ConnectionFailedTrialCounter.SLEEP_BETWEEN_REQUESTS_MILLI);//retry after 5 secs (Thread.sleep)
} else {
throw e;//I give up
}
}
}
return inputStream;
}
private boolean canRetryToConnect() {
return (connectionFailedRetryCounter < connectionFailedMaximumAllowedRetries()) && !canceled;
}
Is this the right way to do this ? or is it already done by the library it self(there is no need to implement anything like this) ?
Here is what the method execute() do
public InputStream execute() throws ConnectionErrorException, NoNetworkAvailableException, ServerException {
if (!Utils.isNetworkAvailable(context)) {
throw new NoNetworkAvailableException();
}
Response response = doExecute();
if (!response.isSuccessful()) {
throw new ServerException(response.code());
}
return response.body().byteStream();
}
private Response doExecute() throws ConnectionErrorException {
Response response;
try {
if (getRequestType() == RequestType.GET) {
response = executeGet();
} else {
response = executePost();
}
} catch (IOException e) {
throw new ConnectionErrorException();
}
return response;
}
You can avoid retrying if you catch NoNetworkAvailableException. Don't retry if you know following attempts will fail anyway.
I would make connectionFailedMaximumAllowedRetries() a constant. I doubt you will need to change the variable at any point.
Implement exponential back off. You could have it retry 10 times. Each time, you multiply the delay by 2 (with a cap of a few minutes). For example:
Try call - failed
Wait 1 second
Try call - failed
Wait 2 seconds
Try call - failed
Wait 4 seconds
...
Try call - succeeded
This is very typical behaviour. In the event of a short outage, the call will be made again very quickly and succeed. In the event of a longer outage, you don't want to be calling constantly every few seconds. This gives your code the best chance of having its call go through. Obviously, attention should be made to not annoy the user if this call is required for a UI change.

Generated web service not receiving parameters

I've generated my web service from WSDL in Netbeans 7.1. For security concerns, I can't show it, but you can safely assume that it's ok, It's been production tested.
I can call the web-service ok. If I make the function return and then dump it, it even returns the correct values. What is wrong though, it never receives any parameters from the SOAP call. This is the way I invoke it in the index.jsp:
try {
Soap.ServiceService service = new Soap.ServiceService();
javax.xml.namespace.QName portQName = new javax.xml.namespace.QName("http://external.example.com/", "ServicePort");
String req = "<getTimestampCount xmlns=\"http://external.example.com/\"><msisdn>656</msisdn></getTimestampCount>";
javax.xml.ws.Dispatch<javax.xml.transform.Source> sourceDispatch = null;
sourceDispatch = service.createDispatch(portQName, javax.xml.transform.Source.class, javax.xml.ws.Service.Mode.PAYLOAD);
javax.xml.transform.Source result = sourceDispatch.invoke(new javax.xml.transform.stream.StreamSource(new java.io.StringReader(req)));
javax.xml.transform.TransformerFactory factory = javax.xml.transform.TransformerFactory.newInstance();
javax.xml.transform.Transformer transformer = factory.newTransformer();
java.io.StringWriter writer = new java.io.StringWriter();
javax.xml.transform.Result stringOut = new javax.xml.transform.stream.StreamResult(writer);
transformer.transform(result, stringOut);
writer.close();
out.print(writer.toString());
} catch (Exception ex) {
out.print(ex.getMessage());
}
And this is the function that returns the result:
public long getTimestampCount(java.lang.String msisdn) throws ParameterException, UnknownException_Exception {
//TODO implement this method
System.out.println(msisdn);
throw new UnsupportedOperationException("Not implemented yet.");
}
The printing always produces null. I can't for the life of me figure out why it's working, finding the right function, but not passing on the values.
Also, I've tested it with this code, and the values returned are correct:
try {
Soap.ServiceService service = new Soap.ServiceService();
Soap.Service port = service.ServicePort();
// TODO initialize WS operation arguments here
java.lang.String msisdn = "5";
// TODO process result here
long result = port.getTimestampCount(msisdn);
out.println("Result = "+result);
} catch (Exception ex) {
out.println(ex.getMessage());
// TODO handle custom exceptions here
}
as expected, this returns a value of 5. This would do fine if I wanted to generate the SOAP response by myself, but I would prefer to receive the response, like the first function does - as SOAP.
Anything else I should post to make this easier? If so, say it, and I'll try to provide everything needed.
I've since solved the problem with these webservices, but I still have no Idea what was wrong with this code.
What I ended up doing, was using the standard syntax, like in the last piece of code. That works perfecty.
Try to add following namespace to your method. It helped me in fixing the same issue.
<tns:getTimestampCount xmlns:tns=\"http://external.example.com/\"><msisdn>656</msisdn>
</tns:getTimestampCount>";

How do I return a String in a try/catch statment?

I am trying to return a String from the following method.
public String openCon() {
try {
Scanner scan = new Scanner(System.in);
URL sitex = new URL("http://" + scan.nextLine());
URLConnection connection = sitex.openConnection();
Object content = sitex.getContent();
BufferedReader in = new BufferedReader(new InputStreamReader(sitex.openStream()));
String str;
String x = "1";
while ((str = in.readLine()) != null) {
x += str;
}
in.close();
return x;
}
catch(Exception e) {
System.out.println(e);
}
}
The problem isn't returning from the try block - the problem is that you aren't returning anything if an exception is thrown. You're catching the exception... but then reaching the end of the method without returning anything. (To put it in more technical terminology: the end of a non-void method should not be reachable.)
Personally, I would just remove the catch block entirely, and add throws declarations for any exceptions which are thrown within the body. You're not really handling the exceptions - you're just printing them out and ignoring them, which is very rarely a good idea. Catching Exception is usually a pretty bad idea to start with.
As an aside, you should also close your BufferedReader and URLConnection values in a finally block so they're closed even in the case of an exception. I'd also suggest either passing a fixed encoding name to InputStreamReader, or using a higher-level HTTP client API which will use the content-type header from the response. Oh, and use StringBuilder instead of string concatenation in a loop.
Why not initialise the variable before the try statement, and place the return statement after it?
If there's an exception before the return statement, the method won't return anything. Since you're not really handling the exception, I recommend you just let it bubble up and handle it at a higher level. This may be the main method if there's no better place. You will need to declare the method as throws IOException and possibly add other exception classes.
Also, use try-with-resources to ensure your instances (BufferedReader and InputStreamReader) are closed properly.
You should return something in the catch block, for example:
catch(Exception e) {
System.out.println(e);
return "";
}
Use:
String result = ""
try{
result = "OK";
}catch (Exception e){
result = e.toString();
}finally{
return result;
}

Categories