How to create an object for testing from external library - java

I have a class for parsing a json response given from an API request, that was made using the restlet framework.
The method responsible for reading the json takes an object from this framework, a Representation,
public QueryResponse readResponse(Representation repr), and I would like to test the functionality of this
My question is, how do I pass a valid Representation object into this method in my JUnit test, considering I do not know how it is constructed from the API call, will I have to implement the call itself within the test to retrieve a workable object or is there another method?

For a unit test, use a mocking framework like mockito:
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.restlet.representation.Representation;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
#ExtendWith(MockitoExtension.class)
public class RestletTest {
#Mock
private Representation representation;
#Test
public void demonstrateMock() {
when(representation.getAvailableSize()).thenReturn(1024l);
ClassToTest t = new ClassToTest();
assertThat(t.callRepresentation(representation), Matchers.is(1024l));
}
}
class ClassToTest {
public long callRepresentation(Representation representation) {
return representation.getAvailableSize();
}
}

Related

Why we need to mock static class before every test case in same class

I have a test class with two test cases . I am using Junit 4. My these test cases are using static class. So I mocked a static class in #BeforeClass method so that it is only mocked once before the start of execution of test cases. but in this case only first test case works fine and rest of all test cases fails. so for that I mocked my static class in #Before method so that it is been mocked before every test case execution. So I want to understand that why is there need to mock the static class before every test case and why cant we mock it only once before start of execution of class.
import com.walmart.fulfillment.encryption.logging.HttpThreadBusinessContext;
import com.walmart.rxorderdetailsfulfillment.data.LabelOverFlowOrderRepo;
import com.walmart.rxorderdetailsfulfillment.models.entity.LabelOverFlowOrder;
import com.walmart.rxorderdetailsfulfillment.models.entity.LabelOverFlowPK;
import com.walmart.rxorderdetailsfulfillment.models.request.LabelOverFlowRequest;
import com.walmart.rxorderdetailsfulfillment.models.response.LabelOverFlowResponse;
import com.walmart.rxorderdetailsfulfillment.util.LabelOverFlowUtility;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.junit.Assert.*;
import static org.mockito.Mockito.when;
#RunWith(PowerMockRunner.class)
#PrepareForTest({LabelOverFlowUtility.class,HttpThreadBusinessContext.class,LabelOverFlowOrderRepo.class,LabelOverFlowResponse.class,LabelOverFlowOrder.class,LabelOverFlowPK.class})
public class LabelOverFlowRequestHandlerTest {
static int count =0;
LabelOverFlowRequest labelOverFlowRequest;
#InjectMocks
LabelOverFlowRequestHandler labelOverFlowRequestHandler;
#Mock
HttpThreadBusinessContext httpThreadBusinessContext;
#Mock
LabelOverFlowOrderRepo labelOverFlowOrderRepo;
#Mock
LabelOverFlowResponse labelOverFlowResponse;
#Mock
LabelOverFlowOrder labelOverFlowOrder;
#Mock
LabelOverFlowPK labelOverFlowPK;
#BeforeClass
public static void initialization(){
//PowerMockito.mockStatic(LabelOverFlowUtility.class);
}
#Before
public void initialization_Before_Every_Test(){
PowerMockito.mockStatic(LabelOverFlowUtility.class);
labelOverFlowRequest = LabelOverFlowRequest.builder().textOverFlow(true).warningOverFlow(true).rxFillId(555).siteNbr(5550).countryCode("US").build();
}
/**
* This test case is use to check success is returned after saving data to DB.
*/
#Test
public void processSaveLabelOverFlowResquestWithSuccess() {
when(LabelOverFlowUtility.getLabelOverFlowPK(Mockito.any())).thenReturn(labelOverFlowPK);
when(LabelOverFlowUtility.getLabelOverFlowOrder(Mockito.any())).thenReturn(labelOverFlowOrder);
when(labelOverFlowOrderRepo.save(Mockito.any())).thenReturn(labelOverFlowResponse);
when(LabelOverFlowUtility.getLabelOverFlowResponse(Mockito.any())).thenCallRealMethod();
Mockito.doReturn(labelOverFlowOrder).when(labelOverFlowOrderRepo).save(Mockito.any());
assertTrue(labelOverFlowRequestHandler.processSaveLabelOverFlowResquest(labelOverFlowRequest).getResponseText().equals("success"));
}
/**
* This test case is ued to check if data is not saved to DB
*/
#Test
public void processSaveLabelOverFlowResquestWithFailure() {
when(LabelOverFlowUtility.getLabelOverFlowPK(Mockito.any())).thenReturn(labelOverFlowPK);
when(LabelOverFlowUtility.getLabelOverFlowOrder(Mockito.any())).thenReturn(labelOverFlowOrder);
when(labelOverFlowOrderRepo.save(Mockito.any())).thenReturn(labelOverFlowResponse);
when(LabelOverFlowUtility.getLabelOverFlowResponse(Mockito.any())).thenCallRealMethod();
Mockito.doThrow(new RuntimeException()).when(labelOverFlowOrderRepo).save(Mockito.any());
assertTrue(labelOverFlowRequestHandler.processSaveLabelOverFlowResquest(labelOverFlowRequest).getResponseText().equals("failure"));
}
}
LabelOverFlowUtility.class is a static class, there should be no need to mock it at all if the methods are deterministic(given same input same thing happens).
I may be misunderstanding how this class operates.

How to get coverage for anonymous class overridden methods using junit mockito

I have below code to retry the request based on response code.
public class Sample {
public static HttpClient getInstance() {
HttpClientBuilder builder = HttpClients.custom();
builder.setServiceUnavailableRetryStrategy(new ServiceUnavailableRetryStrategy() {
int waitPeriod = 200;
#Override
public boolean retryRequest(final HttpResponse response, final int executionCount,
final HttpContext context) {
int statusCode = response.getStatusLine().getStatusCode();
return ((statusCode == 429)&& (executionCount < 3));
}
#Override
public long getRetryInterval() {
return waitPeriod;
}
});
return builder.build();
}
}
While I am writing the unit tests for this getInstance method the overridden methods (retryRequest, getRetryInterval) are not getting covered. How can I write the unit tests to get coverage for these methods as well.
By googling I found we can use ArgumentCaptor.
I have tried the below code, but it does not work.
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verify;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.ServiceUnavailableRetryStrategy;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.protocol.HttpContext;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
#WebAppConfiguration
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = { "classpath:context.xml"})
#PrepareForTest({ HttpClients.class, Sample.class})
public class Sample {
#Mock
HttpClientBuilder clientBuilderMock;
#Mock
CloseableHttpClient clientMock;
#Mock
HttpResponse responseMock;
#Mock
HttpContext contextMock;
#Mock
StatusLine statusLineMock;
#Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
PowerMockito.mockStatic(HttpClients.class);
}
#Test
public void test() throws Exception {
when(HttpClients.custom()).thenReturn(clientBuilderMock);
when(clientBuilderMock.build()).thenReturn(clientMock);
when(responseMock.getStatusLine()).thenReturn(statusLineMock);
when(statusLineMock.getStatusCode()).thenReturn(429);
Sample.getInstance();
ArgumentCaptor<ServiceUnavailableRetryStrategy> argumentCaptor = ArgumentCaptor.forClass(ServiceUnavailableRetryStrategy.class);
verify(clientBuilderMock).setServiceUnavailableRetryStrategy(argumentCaptor.capture());
ServiceUnavailableRetryStrategy retryStrategy = argumentCaptor.getValue();
retryStrategy.retryRequest(responseMock, 3, contextMock);
}
}
argumentCaptor.capture() is always giving me null.I am getting like
org.mockito.exceptions.base.MockitoException:
No argument value was captured!
You might have forgotten to use argument.capture() in verify()...
...or you used capture() in stubbing but stubbed method was not called.
Can anyone help me on this. I would like to test the retryRequest method functionality.
Edit: rephrased the answer to make it easier to read.
Classes that are supposed to be handeled by PowerMockito need to be
declared in the #PrepareForTest annotation.
If annotations are used to create the mocks all annotated classes which are not declared in the #PrepareForTest annotation, are created by Mockito.
If annotations are used to create the mocks and MockitoAnnotations.initMocks(this); is called,
this apparently causes the declaration to be overriden and all mocks are created by Mockito instead.
(Source: https://groups.google.com/forum/#!topic/powermock/yPBey4hr7IU)
Mockito can not handle static or final methods. The mocking operation might fail silently.
The root of your problem is that HttpClientBuilder#setServiceUnavailableRetryStrategy is a
final method and therefore can not be handeled by Mockito.
The solution is that the Mock of HttpClientBulder has to be handeled by PowerMockito.
In accordance with 1. it needs to be declared in the #PrepareForTest annotation.
#PrepareForTest({ HttpClients.class, HttpClientBuilder.class, Sample.class})
If you want to use Annotations to create the mocks, you must not call
MockitoAnnotations.initMocks(this);
(see 2. / I verified this issue with the latest powermockito versions (1.7.4 / 2.0.2))
Else you have to create the mock manually.
HttpClientBuilder clientBuilderMock = PowerMockito.mock(HttpClientBuilder.class);

How do I completely mock out a class with PowerMockito?

I'm reading this documentation on PowerMockito and it has two main examples:
Mocking static methods
Partially mocking a class
but I want to know how to mock an entire class that's created with new. I am looking for the PowerMockito version of Mockito's mock method. This should be able to replace new Foo() in my production code with a Mockito mock(Foo.class), somehow. Here's what I've tried:
import com.PowerMockitoProduction;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpMethod;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.mockito.PowerMockito;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import static org.mockito.Matchers.any;
import static org.powermock.api.mockito.PowerMockito.when;
#RunWith(PowerMockRunner.class)
#PrepareForTest(PowerMockitoProduction.class)
public class PowerMockitoTest {
#Test(expected = UnsupportedOperationException.class)
public void test() throws Exception {
HttpClient mock = PowerMockito.mock(HttpClient.class);
when(mock.executeMethod(any(HttpMethod.class))).thenThrow(UnsupportedOperationException.class);
new PowerMockitoProduction().createClient();
}
}
This test fails with this:
java.lang.Exception: Unexpected exception, expected<java.lang.UnsupportedOperationException> but was<java.lang.IllegalArgumentException>
Here's my production code:
package com;
import org.apache.commons.httpclient.HttpClient;
import java.io.IOException;
public class PowerMockitoProduction {
public void createClient() throws IOException {
HttpClient client = new HttpClient();
client.executeMethod(null);
System.out.println(client);
}
}
With my debugger, I can see that the client is not a mock, like I expected.
I've also tried using:
Object mock = PowerMockito.whenNew(HttpClient.class).withNoArguments().getMock();
But for some reason, that returns a mock that is not completely constructed. I've also tried this:
HttpClient mock = PowerMockito.whenNew(HttpClient.class).withNoArguments().thenReturn(mock(HttpClient.class)).getMock();
But that gives me a ClassCastException on that line. So, what is the correct way to mock out a class completely with PowerMockito?
Unlike this example implies, the reason I'm trying to mock out HttpClient is so that I can call verify it later.
You don't need to call getMock() method to get back the mocked object. Basically, mock an instance of HttpClient, store it in local variable and use that:
#Test(expected=UnsupportedOperationException.class)
public void test() {
HttpClient httpClient = mock(HttpClient.class);
PowerMockito.whenNew(HttpClient.class).withNoArguments().thenReturn(httpClient);
when(httpClient.executeMethod(any(HttpMethod.class))).thenThrow(UnsupportedOperationException.class);
new PowerMockitoProduction().createClient();
verify(httpClient).executeMethod(null);
}

Why does upgrading Mockito from 1.9.5 to 1.10.8 break this Captor?

Given this target code:
...
sessionWrapper.execute(arenaCreateCql, arenaGuid, arenaName, displayName, authorName, createdOn);
...
And Mockito code to validate that line:
...
#Captor
private ArgumentCaptor<Date> createdOnCaptor;
...
#Test
public void testThat_Execute_CreatesNewArena() throws Exception {
...
inOrder.verify(mockSessionWrapper).execute(
eq(arenaCreateCql), eq(testArenaGuid), eq(testArenaName), eq(testArenaDisplayName), eq(testAuthorName), createdOnCaptor.capture());
...
assertNotNull(createdOnCaptor.getValue());
}
This works using Mockito 1.9.5. When upgrading 1.10.8, the verify passes, but the getValue() fails with this error:
org.mockito.exceptions.base.MockitoException:
No argument value was captured!
You might have forgotten to use argument.capture() in verify()...
...or you used capture() in stubbing but stubbed method was not called.
Be aware that it is recommended to use capture() only with verify()
Edit to add MCVE. The following code runs green with Mockito 1.9.5, red with Mockito 1.10.8.
MockitoExample.java:
package org.makeyourcase.example;
import java.util.Date;
public class MockitoExample {
private MockitoExampleExecutor executor;
public void execute(){
executor.execute("var1", new Date());
}
}
MockitoExampleExecutor.java:
package org.makeyourcase.example;
public class MockitoExampleExecutor {
public void execute(Object... bindVariables){
}
}
MockitoExample_UT:
package org.makeyourcase.example;
import java.util.Date;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.junit.Assert.assertNotNull;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.verify;
#RunWith(MockitoJUnitRunner.class)
public class MockitoExample_UT {
#Mock
private MockitoExampleExecutor mockitoExampleExecutor;
#Captor
private ArgumentCaptor<Date> dateCaptor;
#InjectMocks
private MockitoExample subject;
#Test
public void testThat_Execute_InvokesCalendar() throws Exception {
subject.execute();
verify(mockitoExampleExecutor).execute(eq("var1"), dateCaptor.capture());
assertNotNull(dateCaptor.getValue());
}
}
One other piece of info came to light as a result of creating the MCVE - the test works fine if the Date is the only element passed for bindVariables. That is, remove "var1" from target and test code, then the test runs fine under 1.9.5 and 1.10.8. Also, it doesn't matter that the captor is for a Date. The same issue occurs if the parameter is of another type, such as Integer.
Thanks, this is probably a bug, I've created the report on GH-188.
Not sure when it will be fixed though. Fixed in GH-211.

How do I mock static methods in a class with easymock?

Suppose I have a class like so:
public class StaticDude{
public static Object getGroove() {
// ... some complex logic which returns an object
};
}
How do I mock the static method call using easy mock? StaticDude.getGroove().
I am using easy mock 3.0
Not sure how to with pure EasyMock, but consider using the PowerMock extensions to EasyMock.
It has a lot of cool functions for doing just what you need -
https://github.com/jayway/powermock/wiki/MockStatic
Easymock is a testing framework for "for interfaces (and objects through the class extension)" so you can mock a class without an interface. Consider creating an interfaced object with an accessor for your static class and then mock that acessor instead.
EDIT: Btw, I wouldn't recommend doing static classes. It is better to have everything interfaced if you are doing TDD.
Just in Case PowerMock is unavailable for any reason:
You could move the static call to a method, override this method in the instantiation of the tested class in the test class, create a local interface in the test class and use its method in the overidden method:
private interface IMocker
{
boolean doSomething();
}
IMocker imocker = EasyMock.createMock(IMocker.class);
...
#Override
void doSomething()
{
imocker.doSomething();
}
...
EasyMock.expect(imocker.doSomething()).andReturn(true);
Generally speaking, it is not possible to mock a static method without using some sort of accessor, which seems to defeat the purpose of using a static method. It can be quite frustrating.
There is one tool that I know of called "TypeMock Isolator" which uses some sort of Satanic Magic to mock static methods, but that tool is quite expensive.
The problem is, I know of no way to override a static method. You can't declare it virtual. you can't include it in an interface.
Sorry to be a negative nelly.
Adding an exemple on how to implements static mock along regular mock of injected classes with EasyMock / PowerMock, since the linked exemple only shows static mock.
And with the PowerMockRunner the #Mock services are not wired on the #TestSubject service to test.
Let say we have a service we want to test, ServiceOne :
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
#Service
public class ServiceOne {
#Autowired
private ServiceTwo serviceTwo;
public String methodToTest() {
String returnServ2 = serviceTwo.methodToMock();
return ServiceUtils.addPlus(returnServ2);
}
}
Which calls another service that we will want to mock, ServiceTwo :
import org.springframework.stereotype.Service;
#Service
public class ServiceTwo {
public String methodToMock() {
return "ServiceTwoReturn";
}
}
And which calls a final class static method, ServiceUtils :
public final class ServiceUtils {
public static String addPlus(String pParam) {
return "+" + pParam;
}
}
When calling ServiceOne.methodToTest() we get "+ServiceTwoReturn" as a return.
Junit Test with EasyMock, mocking only the injected ServiceTwo Spring service :
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
import org.easymock.EasyMockRunner;
import org.easymock.Mock;
import org.easymock.TestSubject;
import org.junit.Test;
import org.junit.runner.RunWith;
#RunWith(EasyMockRunner.class)
public class ExempleTest {
#TestSubject
private ServiceOne serviceToTest = new ServiceOne();
#Mock
private ServiceTwo serviceMocked;
#Test
public void testMethodToTest() {
String mockedReturn = "return2";
expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
replay(serviceMocked);
String result = serviceToTest.methodToTest();
verify(serviceMocked);
assertEquals("+" + mockedReturn, result);
}
}
Junit Test with EasyMock & PowerMock, mocking the injected ServiceTwo Spring service but also the final class and its Static method :
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;
import static org.powermock.api.easymock.PowerMock.createMock;
import static org.powermock.api.easymock.PowerMock.mockStatic;
import static org.powermock.reflect.Whitebox.setInternalState;
import org.easymock.Mock;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.api.easymock.PowerMock;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
#RunWith(PowerMockRunner.class)
#PrepareForTest(ServiceUtils.class)
public class ExempleTest {
private ServiceOne serviceToTest;
private ServiceTwo serviceMocked;
#Before
public void setUp() {
serviceToTest = new ServiceOne();
serviceMocked = createMock(ServiceTwo.class);
// This will wire the serviced mocked into the service to test
setInternalState(serviceToTest, serviceMocked);
mockStatic(ServiceUtils.class);
}
#Test
public void testMethodToTest() {
String mockedReturn = "return2";
String mockedStaticReturn = "returnStatic";
expect(serviceMocked.methodToMock()).andReturn(mockedReturn);
expect(ServiceUtils.addPlus(mockedReturn)).andReturn(mockedStaticReturn);
PowerMock.replayAll();
String result = serviceToTest.methodToTest();
PowerMock.verifyAll();
assertEquals(mockedStaticReturn, result);
}
}

Categories