Mocking protected function with mockito - java

I am trying to write a unit test for a GWT Servlet.
Therefore i need to mock the getThreadLocalRequest() function of AbstractRemoteServiceServlet so that i dont get NPE's.
The function is protected so according to the mocktio faq it should be possible to mock it as long as I am inside the same package.
So I tried the following:
HttpServletRequest request = mock(HttpServletRequest.class);
svc = spy(new GreetingServiceImpl());
doReturn(request).when(svc).getThreadLocalRequest();
But I get the following error that the function isnt visible:
The method `getThreadLocalRequest()` from the type `AbstractRemoteServiceServlet` is not visible
I would appreciate any advices on the problem or hints on a better solution of my problem.

Mockito can't modify the java rules for visibility and the return value of when(svc) isn't in a package where getThreadLocalRequest() is visible.
Make sure that your test class is in the same package as AbstractRemoteServiceServlet or call the getThreadLocalRequest method is via reflection:
Method getThreadLocalRequestMethod = AbstractRemoteServiceServlet.class.getDeclaredMethod("getThreadLocalRequest");
Object target = doReturn(request).when(svc);
Object regetThreadLocalRequestMethod.invoke(target);

Related

How to test a simple given method using Mockito

I am new to testing with java so it confuses me a little how to write a proper unit test to a method with no parameters and return value. In general the snippet looks like the below:
public class SplitterService {
private SentenceDAO sentenceObject;
private ObjectToXML objectToXML;
private ObjectToCSV objectToCSV;
public SplitterService(int selector, String inputPath, String outputPath) {
this(inputPath);
if (selector == 1)
objectToCSV = new ObjectToCSV(outputPath, size);
if (selector == 2)
objectToXML = new ObjectToXML(outputPath);
}
public void chooseConverter() {
if (objectToCSV != null)
objectToCSV.printRecord(sentenceObject);
if (objectToXML != null)
objectToXML.marshal(sentenceObject);
}
}
There are 3 private fields in the class. There is also a constructor which instantiate a given class. Then in the chooseConverter() method a proper action is taken according to the created object.
Could you please give me some advice how to test the chooseConverter method since there is no return value and a parameter (I know Junit 5 and a little of Mockito). Im not looking for any given solution just a few words how to approach my issue.
The code, in its current form, is not unit-test friendly.
As a last resort, you can test the side effects of ObjectToCSV and ObjectToXML, but lets try to do better than that.
Ideally, the class should provide some injection points to allow you inject new mock instances of ObjectToCSV and ObjectToXML.
There are multiple ways to introduce DI like providing factories for these objects in a constructor, extracting a factory of SplitterService which injects objectToCSV or objectToXML depending on the selector.
These methods require some modifications of the client code.
extracting methods that create instances of objectToCSV and objectToXML from the constructor requires a minimal code change and is transparent to the clients. In such case, you subclass your class and override builder methods to return mocks.
if no modifications to existing code are allowed, I can recommend pulling in Powermock and mocking the constructors. Note: you must be running junit4 vintage engine, as Powermock hasnt been ported to jUnit5 yet.
https://dzone.com/articles/using-powermock-mock
you are looking at a few things here... first check that objectToCSV::printRecord (objectToCSV will be a Mockito mock) is getting called under the condition objectToCSV != null (and objectToXML:: marshal is getting called under objectToXML != null). And also you are looking for ArgumentCaptor most probably, that is to test that objectToCSV::printRecord and objectToXML.marshal is actually getting called with sentenceObject that you set.

best solution for mocking chained calls in Java

I have the following code:
handler = NodeHandler.getINodeHandler(localZone).getITspPlatformHandler().getITspProcessorManagementHandler();
I mocked this out this way:
mockStatic(NodeHandler.class);
INodeHandler iNodeHandler = mock(INodeHandler.class,Mockito.RETURNS_DEEP_STUBS);
when(NodeHandler.getINodeHandler(localZone)).thenReturn(iNodeHandler);
ITspProcessorManagementHandler iTspProcessorManagementHandler =mock(ITspProcessorManagementHandler.class,Mockito.RETURNS_DEEP_STUBS);
when(iNodeHandler.getITspPlatformHandler().getITspProcessorManagementHandler()).thenReturn(iTspProcessorManagementHandler);
After a few row of code an another chained method call comes:
ITspTrafficProcessor processor = NodeHandler.getINodeHandler(localZone, localUI).getITspPlatformHandler().getITspProcessorManagementHandler()
.getITspProcessorHandler(procs[i]).getITspTrafficProcessorHandler(0).getAttributes();
And i mocked this out this way:
when(NodeHandler.getINodeHandler(localZone,UI.CORBA)).thenReturn(iNodeHandler);
when(iNodeHandler.getITspPlatformHandler().getITspProcessorManagementHandler()(+1+).getITspProcessorHandler(anyString())
.getITspTrafficProcessorHandler(anyInt()).getAttributes()).thenReturn(null);
So my question is that, i can not find a better solution than this, because the problem is if i tell the mockito to return null to the handler instead of iTspProcessorManagementHandler then i get a nullpointer exception at (+1+), but if i do the following changes to my code:
INodeHandler iNodeHandler = mock(INodeHandler.class,Mockito.RETURNS_MOCKS);
Than mockito mocks out every method call, and my when-thenReturn statements does not returns what i want for example null. So any advice to do a better solution????
Messy mocking like that is an indication that you could improve abstraction. I'd consider encapsulating that particular logic in a helper interface/class, or to inject the expected type returned by the "trainwreck" to the method/class.

Reflection for testNG

I have a method which uses to restrict the access via spring security. The following is the method :
#PreAuthorize("isAuthenticated() and hasPermission(#request, 'CREATE_REQUISITION')")
#RequestMapping(method = RequestMethod.POST, value = "/trade/createrequisition")
public #ResponseBody
void createRequisition(#RequestBody CreateRequisitionRO[] request,
#RequestHeader("validateOnly") boolean validateOnly) {
logger.debug("Starting createRequisition()...");
for (int i = 0; i < request.length; i++) {
CreateRequisitionRO requisitionRequest = request[i];
// FIXME this has to be removed/moved
requisitionRequest.setFundManager(requisitionRequest.getUserId());
// FIXME might have to search using param level as well
SystemDefault sysDefault = dbFuncs.references.systemDefault
.findByCompanyAndDivisionAndPortfolio(
userContext.getCompany(),
userContext.getDivision(),
requisitionRequest.getPortfolio());
requisitionRequest.setCustodianN(sysDefault.getCustodianN());
gateKeeper.route(requisitionRequest);
}
}
Now i want to use java Reflection at run time to test whether the method is working fine like unit testing.
I have tried to write TestNG for the above which is not working due to the project architecture we have and hence decided to use reflection to test [though which is not a good way of doing this and later we will find the solution for this].
My question is how to create a java reflection class for that method and call the above method and send the URL /trade/createrequisition to server whether it is accessible for the logged in user.
How to do this.
If you want to check if the security annotation is added on the method then in unit test case using java reflection API you can do that.
Find the method using reflection and on that check method.getAnnotation(PreAuthorize.class)
But actually you should test this as a Integration/Functional testing.

EasyMock JUnit testing throws error on the setter method

I am using easyMock for JUnit testing. I want to test a method which gets a Project object as its arguments and sets the modify date of that project and persists it in db.
So e.g.
public void setProject(Project project) {
project.setModifyDate(new Date());
this.reporsitory.persist(project);
}
Now at my test method I have tow mocked projects. For one of them I have set the return value of the getModifyDate. For the other mocked project object I just call the setProject(mockedProject); Now I assertEqual these two project objects.
The problem is easymock throws me an error at the project.setModifyDate(new Date()) of the class which I am testing.
Exception : Unexpected method call project.setModifyDate(..).. Expected:1, Actual:0.
It seems that it does not expect the setter method. Could you please let me know what I am doing wrong.
Thanks.
Yes, it is because of the type of mock object you created. It expects your code to call every method you defined when the one call executes. I cannot remember the exact name but i think it is something like nicemock, versus a strictmock whick makes your code execute every expected method. You should use EasyMock.createNiceMock() for your mock object. The error you have is because it expects you to call setModifyDate but your code didn't for that call.
Your call is unexpected because you must have not put EasyMock.expected for that method. You need to add your mock object .expected(getMethod).andReturns(something).

How is Jmock used with HttpSession and HttpServletRequest

I am new to jmock and trying to mock an HttpSession. I am getting:
java.lang.AssertionError: unexpected invocation: httpServletRequest.getSession()
no expectations specified: did you...
- forget to start an expectation with a cardinality clause?
- call a mocked method to specify the parameter of an expectation?
the test method:
#Test
public void testDoAuthorization(){
final HttpServletRequest request = context.mock(HttpServletRequest.class);
final HttpSession session = request.getSession();
context.checking(new Expectations(){{
one(request).getSession(true); will(returnValue(session));
}});
assertTrue(dwnLoadCel.doAuthorization(session));
}
I have done a bit of searching and it isn't clear to me still how this is done. Feels like I am missing some small piece. Anyone with experience in this can just point me in the right direction.
thanks
You don't need to mock the request object. Since the method you're testing (dwnLoadCel.doAuthorization()) only depends on an HttpSession object, that is what you should mock. So your code would look like this:
public void testDoAuthorization(){
final HttpSession session = context.mock(HttpSession.class);
context.checking(new Expectations(){{
// ???
}});
assertTrue(dwnLoadCel.doAuthorization(session));
}
The question becomes: what do you expect the SUT to actually do with the session object? You need to express in your expectations the calls to session and their corresponding return values that are supposed to result in doAuthorization returning true.
I think you need to tell the JMock context how many times you expect the method to be called before you actually go ahead and call it.
final HttpServletRequest request = context.mock(HttpServletRequest.class);
context.checking(new Expectations(){{
one(request).getSession(true); will(returnValue(session));
}});
final HttpSession session = request.getSession();
I'm not super familiar with JMock but do you actually care in your dwnLoadCel unit test how many times certain methods in the mocked object are called? Or are you just trying to test your class that depends on a HttpSession without an actual Session? If it's the latter than I think that JMock is overkill for you.
You might want to look into either creating a class that implements the HttpSession interface yourself for the purposes of unit testing only (a stub), and running your tests off of that, or you should take a look at dwnLoadCel and determine if it really needs to have a reference to the HttpSession, or if it just needs some properties within the HttpSession. Refactor dwnLoadCel to only depend on what it actually needs (a Map or a certain parameter value within the Session object) - this will make your unit test easier (the dependency on the servlet container goes bye-bye).
I think that you have some level of dependency injection in your class being tested already, but you might be dependent on too broad of an object. The Google Test Blog has had a lot of excellent articles on DI lately that you might find useful (I sure have).

Categories

Resources