Mocking a method with possible null values in powermock - java

I have a method which does the following as a part of the operation:
URL resourceUrl = new File(sampleString1.concat("/")
.concat(sampleString2)).toURI().toURL();
SampleString1 and SampleString2 are populated by the constructor of the class and the class is an abstract class. I used the below line to test this class:
servlet = PowerMockito.mock(MyServlet.class, Mockito.CALLS_REAL_METHODS);
Through this i'm unable to set values of attributes sampleString1 and sampleString2 as i'm not passing them to constructor. Now, when i call my test method in servlet, i get NullPointerExceptions at the above mentioned line because of null values at sampleString1 and sampleString2. I tried to simulate that part by the following:
PowerMockito.whenNew(File.class).withParameterTypes(String.class).
withArguments(Matchers.anyString()).thenReturn(sampleFile);
but still it goes through the string concatanations when new file call is done and throws exception. How can i test this method? I just want to return a sample value for resourceUrl when new file operation is called and proceed with the logic in the method and test the output.
Thanks.

You can use the Whitebox API documented at the following locations:
http://code.google.com/p/powermock/wiki/BypassEncapsulation
http://powermock.googlecode.com/svn/docs/powermock-1.4.12/apidocs/org/powermock/reflect/Whitebox.html
It uses reflection to set the values on an object like so:
MyServlet servlet = PowerMockito.mock(MyServlet.class, Mockito.CALLS_REAL_METHODS);
Whitebox.setInternalState(servlet, "sampleString1", "foo");
Whitebox.setInternalState(servlet, "sampleString2", "bar");
//Test code...

Related

How do I check attributes of an object passed as parameter to a service mocked with Mockito

I am new to Mockito and I am not able to test this scenario:
I want to test a ws controller that takes a json string, parses it and calls a method from a service with the resulted object.
I have decided to mock the service dependency with Mockito and I am trying to verify that the correct method from this mock is called with the correct parameter.
I think the problem is that the verify method compares the references of the two objects. Is there a way to compare certain attributes of the object passed as parameter?
Is there a solution other than overriding the equals method of the "DummyObj" from the example?
*short recap: the controller.recive( json ) method takes a string and calls service.onMessage( resultedObj ) with the parsed obj as param. the onMessage method is not returning anything. *
The test looks like this:
#Test
public void test() {
DummyObj dummyObj = new DummyObj();
String dummyObjJson = new Gson().toJson(dummyObj);
controller.recive(dummyObjJson);
verify(mockedService).onMessage(dummyObj);
}
One way is using ArgumentMatchers.argThat
verify(mockedService)
.onMessage(ArgumentMatchers.argThat(obj->obj.getName().equals(dummyObj.getName())));
And the another way is using ArgumentCaptor
ArgumentCaptor<DummyObj> argument = ArgumentCaptor.forClass(DummyObj.class);
verify(mock).doSomething(argument.capture());
assertEquals("John", argument.getValue().getName());

NullPointerException when using Mockito thenCallRealMethod

I have a question regarding using Mockito thenCallRealMethod. I've read the warnings about using this function; basically I want to write this into my test to futureproof my application logic, because it's being used as a library and I want to make sure users of my library have futureproof protection.
My test case looks like this:
#Test
public void Test() {
when(restTemplate.postForEntity(...)).thenReturn(new ResponseEntity<>(realObjectMapper.writeValueAsString(data), HttpStatus.OK));
when(objectMapper.readValue(realObjectMapper.writeValueAsString(data), TestData.class)).thenCallRealMethod();
TestData result = tested.callMethod(...);
....
}
TestData is a simple POJO which contains a bunch of fields but nothing particularly interesting, and data is an instance of TestData. objectMapper is a mocked instance of FasterXML Jackson ObjectMapper, and realObjectMapper is a real (unmocked) instance of the same class.
The problem I'm having is a NullPointerException when my application attempts to execute objectMapper.readValue (on the mocked instance) as per the thenCallRealMethod on the second line of the test. I've verified that when I pass the same inputs to realObjectMapper.readValue then it executes fine, so there is nothing wrong with the input. What am I missing?
Stack trace:
java.lang.NullPointerException
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2842)
.... (my code here)
When you use a mocked object then the real object is not initialized. That means any property even with a default value will be null.
In my case I had a property injected with #Value from a properties file, but if I define a default value it happens the same, it is null when it is going to be used.
Solution: Yo have to check which is the property causing the null pointer exception on the method and then either mock a getter that returns the expected value of that property and call the getter from your real method or set its value with a setter from the test, after the mock object is created

Unable to mock a class with a method that chains an interface in Java

I am trying to mock a class with Mockito that has a method which chains an interface. The class is mocked successfully but when it calls the interface a null pointer is thrown. The code looks as below:
mock = Mockito.mock(MyProcess.class);
process = mock.getProcess()
.getService() //Interface throwing null exception
.startProcessInstanceByKey("String argument");
I got this solution and tried to follow the example on the page below but its not working: https://static.javadoc.io/org.mockito/mockito-core/2.13.0/org/mockito/Mockito.html#RETURNS_DEEP_STUBS
Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);
// note that we're stubbing a chain of methods here: getBar().getName()
when(mock.getBar().getName()).thenReturn("deep");
// note that we're chaining method calls: getBar().getName()
assertEquals("deep", mock.getBar().getName());
The example above is not working
You need to mock the retuning Service, too. All external dependencies of you classes need to be mocked and if you doesn´t do this you get null.
processMock = Mockito.mock(MyProcess.class);
serviceMock= Mockito.mock(Service.class);
Mockito.doReturn(serviceMock).when(processMock).getService();
Mockito.doReturn(<VALUE>).when(serviceMock).startProcessInstanceByKey("String argument");
You need to mock every step with external values - this is how it works.

Mock Documentum IDfSession using Mockito

I have the following (simplified) function which I wish to check using JUnit:
protected IDfCollection getCollection(IDfSession session) throws DfException{
IDfQuery dfcQuery = new DfQuery();
dfcQuery.setDQL(MY_DQL);
return dfcQuery.execute(session, IDfQuery.READ_QUERY);
}
I have successfully tested it using real IDfSession, but I would like do it without connecting to the repository. So I tried to mock empty IDfSession using:
IDfSession mockedSession = Mockito.mock(IDfSession.class);
But I was given NullPointerException:
Caused by: java.lang.NullPointerException
at java.util.StringTokenizer.<init>(StringTokenizer.java:182)
at java.util.StringTokenizer.<init>(StringTokenizer.java:204)
at com.documentum.fc.internal.util.SoftwareVersion.<init>(SoftwareVersion.java:53)
at com.documentum.fc.client.DfQuery.runQuery(DfQuery.java:136)
at com.documentum.fc.client.DfQuery.execute(DfQuery.java:208)
Not knowing what actually went wrong (which function of the mocked object returned null which was not expected) I created a simple class implementing IDfSession interface and used code coverage tool to check which function was called. I hoped to mock behavior of the function later using mockito. I seemed to be getServerVersion so I changed returned null to real value "6.5.0.355 SP3P0600 Linux.Oracle". Next called function was getBatchManager so I mocked returned object here as well. But now I get:
Caused by: java.lang.ClassCastException: com.example.model.mock.IDfSessionMocked cannot be cast to com.documentum.fc.client.impl.session.ISession
I tried to implement ISession interface in the IDfSessionMocked class, but it does not compile, for instance because one of the used types (namely com.documentum.fc.client.impl.session.ISessionListener) is not visible.
Here: http://www.informedconsulting.nl/blog/?p=187 I found information how to do it using powerMock. Another difference is that object is taken directly from session not using IDfQuery.
What should I do?
Update after comment
getBatchManager function was mocked and now it returns anonymous inner class object, with all the returned values set to false or 0 depending on the expected returned type. Function isFlushBatchOnQuery has been called according to coverage tool.
I am not an expert of Documentum but I think you need a more complex object, you could have a look at this repo https://github.com/ValentinBragaru/dfc-mock
IDfSessionMock is what you need I think.
I hope it helps.

mockito - how to check an instance inside a method

I am new to Mockito, I am trying to verify the attributes of an object which gets created inside a method.
pseudo code below:
class A{
...
public String methodToTest(){
Parameter params = new Parameter(); //param is basically like a hashmap
params.add("action", "submit");
return process(params);
}
...
public String process(Parameter params){
//do some work based on params
return "done";
}
}
I want to test 2 things:
when I called methodToTest, process() method is called
process() method is called with the correct params containing action "submit"
I was able to verify that process() is eventually called easily using Mockito.verify().
However trying to check that params contains action "submit" is very difficult so far.
I have tried the following but it doesn't work :(
BaseMatcher<Parameter> paramIsCorrect = new BaseMatcher<Parameter>(){
#Overrides
public boolean matches(Object param){
return ("submit".equals((Parameter)param.get("action")));
}
//#Overrides description but do nothing
}
A mockA = mock(A);
A realA = new A();
realA.methodToTest();
verify(mockA).process(argThat(paramIsCorrect))
Any suggestion ?
If you have got verify() to work, presumably it is just a case of using an argument matcher to check the contains of params.
http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#3
The example given in the above docs is verify(mockedList).get(anyInt()). You can also say verify(mockedList).get(argThat(myCustomMatcher)).
As an aside, it sounds like you are mocking the class under test. I've found that this usually means I haven't thought clearly about either my class or my test or both. In your example, you should be able to test that methodToTest() returns the right result irrespective of whether or not it calls process() because it returns a String. The mockito folk have lots of good documentation about this sort thing, particularly the "monkey island" blog: http://monkeyisland.pl/.
Just pass Parameter in as a constructor argument to a constructor of the class A, then use a mocked instance/implementation of Parameter in your test and verify on the mock. That is how it is normally done - you separate your classes and compose them using constructor injection, that enables you to pass in mocks for testing purposes (it also allows rewiring the application and exchanging some commons a lot easier).
If you need to create Parameter on every function invocation you should use a factory that creates Parameter instances and pass that in. Then you can verify on the factory as well as the object created by the factory.

Categories