Mocking call to static method call inside spy method - junit

Pretty new to mockito. Stuck with a basic thing:
#Override
public void updateMeeting(Meeting meeting, Meeting oldMeeting, List<MeetingOccurrence> oldMeetingOccurrences, List<MeetingOccurrence> newMeetingOccurrences) {
Predicate<Meeting> update = (e) -> MeetingUtil.needReminderChange(oldMeeting, meeting, oldMeetingOccurrences, newMeetingOccurrences);
// DO STUFF
if(ConfUtil.isRecurrenceMeeting(meeting.getType()) && meeting.getType() == oldMeeting.getType()){
update = update.or((e) -> recurringMeetingDurationChange(oldMeetingOccurrences, newMeetingOccurrences));
}
}
if (update.test(meeting)) {
sendEvent(meeting, MeetingConstants.MTG_CHANGE_EVEN_TYPE_UPDATE, getNotifiers(meeting, oldMeeting));
}
}
//---
TEST CLASS
public void testUpdateMeeting(){
MeetingNotifyService meetingNotifyService = Mockito.spy(MeetingNotifyServiceImpl.class);
Meeting meeting = Mockito.spy(Meeting.class);
Meeting oldMeeting = Mockito.spy(Meeting.class);
meeting.setType(Constants.MTG_TYPE_RECURRENCE);
meetingNotifyService.updateMeeting(meeting,oldMeeting,null,null);
}
//--
Problem is that when the code hits this line: ConfUtil.isRecurrenceMeeting it fails. It happens because of static block code inside ConfUtil. How can I tell mockito to not actually call ConfUtil.isRecurrenceMeeting and just return true. I cannot use powermockito

You can use PowerMockito to mock the static method. But the best way I would suggest you to avoid PowerMockito and have your code designed as testable code. So you don't have to mock a static method, consider to have it as a singleton service and you just have to mock a service normally.

Related

Mock a void method

//Original method:
#Autowired
private ConversionServiceValidator validator;
public CRSConversionResult convertCRS(ConvertCrsVo convertCrsVo) throws Exception {
if (validator.isSameSourceAndTarget(convertCrsVo))
throw new ValidationException(Constants.BADREQUEST);
if (convertCrsVo.getPreferredTransforms() != null) {
List<TransformVo> preferredTransformList = new ArrayList<>();
for (TransformVo transformVo : convertCrsVo.getPreferredTransforms()) {
preferredTransformList.add(getPerfByCode(transformVo));
}
convertCrsVo.setPreferredTransforms(preferredTransformList);
}
convertCrsVo.setSourceCRS(getCrsVoByCode(convertCrsVo.getSourceCRS()));
convertCrsVo.setTargetCRS(getCrsVoByCode(convertCrsVo.getTargetCRS()));
convertCrsVo = validator.replaceCoordinates(convertCrsVo);
logger.info("ShellGeodeticService::convertCRS::Request to GeoCalService convertpoints::" + mapper.writeValueAsString(convertCrsVo));
ConvertPointsResponse response = geoCalService.convertCRS(convertCrsVo);
CRSConversionResult result = new CRSConversionResult();
result.setCriteriaMessage(response.getCriteriaMessage());
result.setResultPoints(response.getResultPoints());
result.setTransformName(response.getTransformName());
result.setTransformDescription(response.getTransformDescription());
// added schema as per pbi 195298
List<ConvertedTransformsResult> transformsResults = new ArrayList<>();
if (response.getTransforms() != null || !response.getTransforms().isEmpty())
response.getTransforms().stream().forEach(
t -> transformsResults.add(new ConvertedTransformsResult().getConvertedTransformsResult(t)));
result.setTransforms(transformsResults);
String logmessage=generateLogMessage(result,convertCrsVo);
logger.info(logmessage);
validator.isResponseValid(result);
return result;
}
//The testcase for the above method
#Test
public void testconvertCRSJob() throws Exception{
ConvertCrsVo convertCrsVo = TestDataFactory.getConvertCrsVo();
CRSConversionResult crsConversionResult = TestDataFactory.getCRSConversionResult();
ConversionServiceValidator conversionServiceValidatorMock = mock(ConversionServiceValidator.class);
Mockito.when(geoCalService.convertCRS(Mockito.any()))
.thenReturn(TestDataFactory.getConvertPointsResponse(convertCrsVo));
Mockito.when(validator.replaceCoordinates(convertCrsVo))
.thenReturn(TestDataFactory.getConvertCrsVo());
Mockito.when(geoCalService.search(Mockito.any(SearchFilter.class)))
.thenReturn(TestDataFactory.getSearchResultResponseForCRS());
Mockito.when(shellGeodeticService.convertCRS(convertCrsVo))
.thenReturn(TestDataFactory.getCRSConversionResult());
shellGeodeticService.convertCRSJob();
}
The error that i am getting is as below:
org.mockito.exceptions.misusing.CannotStubVoidMethodWithReturnValue:
'isResponseValid' is a void method and it cannot be stubbed with a return value!
Voids are usually stubbed with Throwables:
doThrow(exception).when(mock).someVoidMethod();
If you're unsure why you're getting above error read on.
Due to the nature of the syntax above problem might occur because:
1. The method you are trying to stub is overloaded. Make sure you are calling the right overloaded version.
2. Somewhere in your test you are stubbing final methods. Sorry, Mockito does not verify/stub final methods.
3. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies -
- with doReturn|Throw() family of methods. More in javadocs for Mockito.spy() method.
4. Mocking methods declared on non-public parent classes is not supported.
at com.shell.geodetic.GeodeticConvertionApiAppTests.testconvertCRSJob(GeodeticConvertionApiAppTests.java:1783)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
Can someone help me on how to stub the void method "isResponseValid" ? I tried around 100 combinations that i saw in SOF and nothing worked. Thanks for the help in advance.
*Edit
Class ConversionServiceValidator {
public void isResponseValid(CRSConversionResult response) throws InvalidDataException {
if (response.getResultPoints().isEmpty() || response.getResultPoints() == null) {
throw new ValidationException("Request body has incorrect format");
} else {
for (Point point : response.getResultPoints()) {
if (point.getX().trim().equals("0") || point.getY().trim().equals("0")) {
throw new InvalidDataException(400, "Bad Request", "WARNING: Not all points could be converted",
response);
}
}
}
It is a mock #InjectMocks ShellGeodeticService shellGeodeticService;
shellGeodeticService is not a mock. #InjectMocks is used for the class under test, where the mocks are injected into.
That implies you can not use
Mockito.when(shellGeodeticService.convertCRS(convertCrsVo))
.thenReturn(TestDataFactory.getCRSConversionResult());
in your test as only mocks(or spys) can be used within Mockito.when.
Actually im trying to run test case for shellGeodeticService.convertCRS() and since it calls isResponseValid method internally , i have to mock that also right?
No, that is incorrect. If validator is a mock every method invocation will do nothing by default. So, unless you want to throw an exception, you do not need to define anything.
As your question lacks some details, I assume a complete version of your test could be similiar to this:
#InjectMocks
ShellGeodeticService shellGeodeticService;
#Mock
ConversionServiceValidator validator;
#Mock
... geoCalService; // some unknown class
#Test
public void testconvertCRSJob() throws Exception{
ConvertCrsVo convertCrsVo = TestDataFactory.getConvertCrsVo();
// Note sure whether this is correct by your logic as there is no `replacement` happening.
Mockito.when(validator.replaceCoordinates(convertCrsVo)).thenReturn(convertCrsVo);
Mockito.when(geoCalService.convertCRS(Mockito.any())).thenReturn(TestDataFactory.getConvertPointsResponse(convertCrsVo));
CRSConversionResult result = shellGeodeticService.convertCRS();
// do some assertions on the result
}
As validator is a mock:
validator.isSameSourceAndTarget(convertCrsVo) returns false be default
validator.isResponseValid( ... ) does nothing by default
As you did not add the methods getCrsVoByCode, getPerfByCode and generateLogMessage take note that if there are any further interactions with the mocked objects you'll need to add them.
(eg.: a call to geoCalService.search is not visible in your test code, so I removed the behaviour definition from the test displayed above)

Unable to Mock functions inside static method Powermock

I am writing unit test for the below code using junit and mockito
public class Abc implements Runnable
{
private static ServerSocket server;
private static int port;
public Abc(int cPort)
{
port = cPort;
}
public void run()
{
init();
}
public static void init()
{
try {
server = new ServerSocket(port);
...something...
client.close();
}
}
catch(IOException e)
{
System.out.println("Exception inside init()...");
e.printStackTrace();
}
}
};
Unit test I have written
#RunWith(PowerMockRunner.class)
#PrepareForTest({ServerSocket.class})
public class abcTest {
#Mock (name = "server") //same name as private var.
ServerSocket mockServer;
#InjectMocks
Abc abc;
#Test
public void testInit() throws Exception {
int port = 1880;
Socket mockClient = Mockito.mock(Socket.class);
PowerMockito.whenNew(ServerSocket.class).
withArguments(anyInt()).thenReturn(mockServer);
abc = new Abc(port);
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
};
But the call always go to original function definition. I am using junit 4.11 with mockito 2.28.2 and powermockito 2.0.2. I'm using java after a long time. Now its feel like kind of new. Please correct me if anything wrong in the code also.
You will need to change your PrepareForTest annotation
to #PrepareForTest({Abc.class}).
From the PowerMockito docu:
This annotation tells PowerMock to prepare certain classes for testing. Classes needed to be defined using this annotation are typically those that needs to be byte-code manipulated
In this case that refers to the class which creates the new instance of ServerSocket. ServerSocket itself is a non-final public class that does not require special handling from PowerMockito (instead Mockito can deal with this class on its own).
You could also change your test to do the following:
#Test
public void testInit() throws Exception {
int port = 1880;
ServerSocket mockServer = Mockito.mock(ServerSocket.class);
PowerMockito.whenNew(ServerSocket.class)
.withArguments(Mockito.anyInt()).thenReturn(mockServer);
Abc.port = port;
Abc.init();
PowerMockito.verifyNew(ServerSocket.class).withArguments(port);
}
(This first point is unrelated to whether the test fails or succeeds)
I do not know why you mix object's and static method behaviour together, but I think you should change that.In the test instead of creatic an ABC object, just could just set the static port variable directly.
Or alternatively change the whole ABC class into an object.
#InjectMocks failed for me as there is no default constructor
(Actually I got an error message in the console when trying to execute your code)
Additonaly you create a new instance of ABC in your test, which would have overwritten the things done by the annotations. Also as server is created during the init call, there is no need to inject a mock for it.
powermockito 2.0.2 actually depends on junit 4.12, so I am not sure what effects downgrading to an older version might have.
Socket mockClient seemed somewhat unrelated to the code your posted, so I removed it from my example in the answer, however as you use a client (I assume that is your Socket) in your code your probably need to do some mocking for that as well and provide the mock to the method accordingly.

Unable to mock URL class using PowerMockito/Mockito

I am trying to use PowerMockito to mock the creation of the java.net.URL class in my code that I'm testing. Basically, I want to prevent the real HTTP request from occurring and instead 1) check the data when the request is made and 2) supply my own test data back on a mocked response. This is what I'm trying:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class })
public class Test {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
...
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
...
}
The code that I want to test looks like this:
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
Earlier in my test scenario I mock the wlInvokeUrlString to match "MyURLString". I've also tried using various other forms of the whenNew line, trying to inject the mock. No matter what I try, it never intercepts the constructor. All I want to do is "catch" the call to openConnection() and have it return my mocked HTTP connection instead of the real one.
I have mocked other classes ahead of this one in the same script and these are working as expected. Either I need a second pair of eyes (probably true) or there is something unique about the URL class. I did notice that if I use "whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to "thenAnswer" I could get it to trigger. Only problem is I never get the URL call for my code. What I see is an invocation of the 3-argument constructor for URL.class with all nulls for the parameters. Could it be this class is from the Java runtime and is bootstrapped by the test runner? Any help is much appreciated.
It's a common mistake when use PowerMockito.whenNew.
Note that you must prepare the class creating the new instance of MyClass for test, not the MyClass itself. E.g. if the class doing new MyClass() is called X then you'd have to do #PrepareForTest(X.class) in order for whenNew to work
From Powermock wiki
So, you need a bit change your test and add to #PrepareForTesta class which create a new instance of URLlike:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ URL.class, MockedHttpConnection.class , ConnectionUser.class})
public class URLTest {
public class URLTest {
private ConnectionUser connectionUser;
#Before
public void setUp() throws Exception {
connectionUser = new ConnectionUser();
}
#Test
public void testName() throws Exception {
URL mockedURL = PowerMockito.mock(URL.class);
MockedHttpConnection mockedConnection = PowerMockito.mock(MockedHttpConnection.class);
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL);
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
connectionUser.open();
assertEquals(mockedConnection, connectionUser.getConnection());
}
}
where:
public class ConnectionUser {
private String wlInvokeUrlString = "MyURLString";
private HttpURLConnection connection;
public void open() throws IOException {
URL wlInvokeUrl = new URL(wlInvokeUrlString);
connection = (HttpURLConnection) wlInvokeUrl.openConnection();
}
public HttpURLConnection getConnection() {
return connection;
}
}
I'm not sure the difference between .withParameterTypes(x) and .withArguments(x) but I believe you need to set it up as follows for your code to work. Give it a try and let me know if this doesn't help.
PowerMockito.when(mockedURL.openConnection()).thenReturn(mockedConnection);
PowerMockito.whenNew(URL.class).withArguments(Mockito.anyString()).thenReturn(mockedURL);
The problem is that the arguments of the real call are not matching with the expected in your mock.
PowerMockito.whenNew(URL.class).withParameterTypes(String.class).withArguments("MyURLString").thenReturn(mockedURL) will return mockedURL only the call is new URL("MyURLString").
If you change it to:
PowerMockito.whenNew( URL.class ).withParameterTypes( String.class )
.withArguments( org.mockito.Matchers.any( String.class ) ).thenReturn( mockedURL );
It will catch any string passed to the constructor URL(String) (even null) and return your mock.
When you tried
"whenNew(URL.class).withAnyArguments()" and change the "thenReturn" to
"thenAnswer" I could get it to trigger. Only problem is I never get
the URL call for my code. What I see is an invocation of the
3-argument constructor for URL.class with all nulls for the
parameters.
PowerMock will try to mock all constructors (org.powermock.api.mockito.internal.expectation.DelegatingToConstructorsOngoingStubbing.InvokeStubMethod at line 122) then it calls the first one (with 3 arguments) and mock its answer. But the subsequent calls will return the already mocked one because you told it to mock for any arguments. That's why you see just one call with null, null, null in your Answer.

Call a Rest method with mockito

I use Jersey and I have the following Rest function which returns a JSON string when my server is deployed:
#GET
#Path("getallemployees")
#Produces("application/json")
public Response getAllEmployees() {
//building the entity object which is List<Employee>
return Response.ok(entity).build();
}
I need to develop some unit tests (not integration testing) and I want to somehow mock the HTTPRequest that invokes this method and then get the json String. The best option would be to use mockito for this.
Is there any suggestion on how to do it ?
Thanks !!
The problem is that the method returns a Response object to the caller which is deep within the framework code. It doesn't return JSON strings.
You can use Mockito, if you need to mock something inside the method itself. That should work.
But you may need to take the value returned by the method and convert it to JSON like this if you are using Jackson with Jersey.
Response response = getAllEmployees();
Object retval = response.getEntity();
try {
ObjectMapper mapper = new ObjectMapper();
// I like this formatting. You can change it.
mapper.configure(Feature.INDENT_OUTPUT, true);
mapper.configure(Feature.WRITE_ENUMS_USING_TO_STRING, true);
mapper.configure(Feature.USE_ANNOTATIONS, false);
mapper.configure(Feature.FAIL_ON_EMPTY_BEANS, false);
mapper.setSerializationInclusion(Inclusion.NON_NULL);
mapper.getSerializationConfig().setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
mapper.getSerializationConfig().withSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
String json = mapper.writeValueAsString(retval);
... assert something about the string
} catch (JsonProcessingException e) {
// do something
} catch (IOException e) {
// do something
}
Some of this is guess work and speculation on my part but it may help. You could try using the Jersey Test Framework with the InMemoryTestContainerFactory:
It starts Jersey application and directly calls internal APIs to handle request created by client provided by test framework. There is no network communication involved. This containers does not support servlet and other container dependent features, but it is a perfect choice for simple unit tests.
It looks like to use it, all you need to do is extend JerseyTest and then override getTestContainerFactory() and follow the rest of the instructions, e.g.:
public class EmployeeResourceTest extends JerseyTest {
#Override
protected Application configure() {
// set up employee resource with mock dependencies etc...
return new ResourceConfig().registerInstances(employeeResource);
}
#Test
public void getAllEmployees() {
final String response = target("getallemployees").request().get(String.class);
// assert etc...
}
}
I used registerInstances instead of registerClasses in configure() as it looks like you can present a ready made Resource but set up with any mock dependencies you may want - although I haven't tried this myself.
The test class is a bit inflexible as you can only do one-time set up of dependencies in the configure() method, so it might be worth investigating using the MockitoJUnitRunner - although I'm not sure if it will work with the JerseyTest inheritance. It could allow you to do add behaviour to mocks in each #Test method, e.g.:
#Mock
private EmployeeResourceDependency dependency;
#InjectMocks
private EmployeeResource employeeResource;
// configure() as above but without mock setup up etc...
#Test
public void getAllEmployees() {
given(dependency.getEmployees()).willReturn(...);
// etc...
But like I said it might not be possible to mix them at all.

Intercepting the concrete implementation (as opposed to service) using Castle Windsor

I'm experimenting with interception in Castle Windsor and notice that interceptors seem to be created as decorators of my service interface.
In other words, if I have an interface "ISomethingDoer" and a concrete "ConcreteSomethingDoer", the proxy implements ISomethingDoer but does not inherit from ConcreteSomethingDoer.
This is fine, and no doubt by design, but what I'm wondering is whether I can intercept protected virtual methods in my concrete classes that wouldn't be known by the public interface. I am doing this in order to add logging support, but I might want to log some of the specific internal details of a class.
In my slightly unimaginative test case I have this:
public interface ISomethingDoer
{
void DoSomething(int Count);
}
[Loggable]
public class ConcreteSomethingDoer : ISomethingDoer
{
public void DoSomething(int Count)
{
for (var A = 0; A < Count; A++)
{
DoThisThing(A);
}
}
[Loggable]
protected virtual void DoThisThing(int A)
{
("Doing a thing with " + A.ToString()).Dump();
}
}
So what I want to do is log calls to "DoThisThing" even though it's not part of the interface.
I've managed to get this working in Autofac. (I've created a Linqpad script here: http://share.linqpad.net/frn5a2.linq) but am struggling with Castle Windsor (see http://share.linqpad.net/wn7877.linq)
In both cases my interceptor is the same and looks like this:
public class Logger : IInterceptor
{
public void Intercept(IInvocation Invocation)
{
String.Format("Calling method {0} on type {1} with parameters {2}",
Invocation.Method.Name,
Invocation.InvocationTarget.GetType().Name,
String.Join(", ", Invocation.Arguments.Select(a => (a ?? "*null*").ToString()).ToArray())).Dump();
Invocation.Proceed();
"Done".Dump();
}
}
What I really want to do is say "any classes with a [Loggable] attribute, should use the logging interceptor". In the Autofac example I've specifically attached a logger to the registration, whereas with Castle I'm using an IModelInterceptorsSelector which looks like this:
public class LoggerInterceptorSelector : IModelInterceptorsSelector
{
public bool HasInterceptors(ComponentModel Model)
{
return Model.Implementation.IsDefined(typeof(LoggableAttribute), true);
}
public InterceptorReference[] SelectInterceptors(ComponentModel Model, InterceptorReference[] Interceptors)
{
return new[]
{
InterceptorReference.ForType<Logger>()
};
}
}
Finally, the code to execute all this is:
var Container = new WindsorContainer();
Container.Register(
Component.For<Logger>().LifeStyle.Transient
);
Container.Kernel.ProxyFactory.AddInterceptorSelector(new LoggerInterceptorSelector());
Container.Register(
Component.For<ISomethingDoer>()
.ImplementedBy<ConcreteSomethingDoer>()
.LifeStyle.Transient
);
var Doer = Container.Resolve<ISomethingDoer>();
Doer.DoSomething(5);
When run I would expect to see "Calling method DoThisThing with parameters x" for each time the method is called. Instead I only get the call to DoSomething logged.
I can see why Castle Windsor is doing this, but I'm wondering if there is a way to tweak the behaviour?
(As a side-note I don't want to use Windsor's own interceptor attributes as I don't want to introduce dependencies to Castle outside of my composition root.)
I have tried resolving the ConcreteSomethingDoer specifically and this works, but not if I'm resolving the ISomethingDoer.
Apologies for the long post, and also apologies because I am pretty new to Castle Windsor!
I you could register like:
Container.Register(
Component.For<ISomethingDoer, ConcreteSomethingDoer>()
.ImplementedBy<ConcreteSomethingDoer>()
.LifeStyle.Transient
);
This should create a class proxy by deriving from ConcreteSomethingDoer. However this won't work with dynamic interceptors. However you probably can work around that by creating a facility which registers the interceptor when needed.