mocking class with annotated methods - java

I have concrete class that I want to mock. There are several annotated methods with annotations. I want to create class mock but I need to preserve that annotations.
I tried easymock. It subclasses my class without problems, but does not preserve annotations.
I would like to preserve annotations in easymock. If that is impossible are there any other mocking solution?

I prefer mockito which uses a different paradigm for mocking out classes. You don't have to subclass everything like you do with easymock.
http://code.google.com/p/mockito/
The javadoc itself has a ton of information about how to utilize the library
http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html#2
Her is a short example from their documentation.
//You can mock concrete classes, not only interfaces
LinkedList mockedList = mock(LinkedList.class);
//stubbing
when(mockedList.get(0)).thenReturn("first");
when(mockedList.get(1)).thenThrow(new RuntimeException());
//following prints "first"
System.out.println(mockedList.get(0));
//following throws runtime exception
System.out.println(mockedList.get(1));
//following prints "null" because get(999) was not stubbed
System.out.println(mockedList.get(999));
//Although it is possible to verify a stubbed invocation,
//usually it's just redundant
//If your code cares what get(0) returns then something else
//breaks (often before even verify() gets executed).
//If your code doesn't care what get(0) returns then it should
not be stubbed. Not convinced? See here.
verify(mockedList).get(0);
So with this library you setup your tests and stub out the methods that you are interested in testing.
Hope you found this useful.

Related

Is there a an equivalent doCallRealMethod for spies (aka doCallMockMethod)?

I need to mock out a class due to one third party required dependency, so I can unit test it (I cannot remove this dependency).
So what I've done is mocked out the class and then utilized Mockito.doRealMethod() for all the function calls, but I feel this sort of abstracts what is being really done.
When in reality I want the real class and just want to mock out that one call.
Partial mocking of a class is supported via spy in Mockito. See the Mockito documentation on partial mocks for more information.
Another possibility may be to use org.mockito.Mockito.CALLS_REAL_METHODS, such as:
YourClass YOUR_MOCK = Mockito.mock( YourClass.class, CALLS_REAL_METHODS );
You can override the real method on a spy like
Mockito.doReturn("foobar").when(mySpy).myMethod();

Unit testing save methods when return type is void

Is there any way to write unit tests for save methods in DAO layer when return type is void? I'm using Log4j, Junit in spring boot project.
I've tried many ways to assert them. But since they aren't returning any value i wasn't able to assert them.
If the method is void, then it has side-effects, otherwise it would be a no-op.
So you call the method, then check if the desired side-effect happened.
E.g. setFoo(7) should mean that getFoo() returns 7, though unit testing simple getter/setter methods is a waste of time.
It is common to use mock objects to detect the side-effects, but it all depends on what the expected side-effect is. See: What is the purpose of mock objects?
There are several ways to unit test a method that returns void.
Change the method so that it returns a value even though you don't use that value. This is NOT the best way, but I note it here for completeness.
The method likely changes the state of the object in some way. A file was saved, a value was stored somewhere, parameters have been changed, etc. So check the values that should have been changed. You can read back a saved file, a changed variable, data in a test database, etc.
Mock objects can be used to determine if a method was called and what the behavior was. There are a number of mock object frameworks for Java, including Easy Mock, JMockit and Mockito. How to use a mock framework is beyond the scope of this answer, but I did include links to the various sites for your reference.
If bad inputs are given to the method it may throw an exception. It is a good idea to do this to test the error handling of your methods.
According to your comments you need to write an unit test for a save method. Try this example code,
#Autowired
private EmployeeDAO employeeDAO;
#Test
public void whenValidEmployee_thenShouldSave()
{
EmployeeEntity employee = new EmployeeEntity("1", "Department Name", "Role"); //id, department name and role are passing as constructor parameters
employeeDAO.save(employee);
List<EmployeeEntity> employees = employeeDAO.findAll();
//Assert
Assert.assertEquals(employee.getId(), employees.get(0).getId());
}
Writing a testable code is important as a developer in modern days. You should understand that a method with void, is bad for a single reason.it is not testable by any means. i would suggest you below actions to take
Improve your code with a relevant return type.
It's worth applying DbUnit, rather than applying just Junit to test
your DAO layer.
#Teguwih

How to spy a class who has an Annotation with Mockito?

I want to spy a class who has a custom Annotation, but when I try to get annotations it has not anything.
My class is defined as:
#FisaEntity(name="TCRB_AFL_AFFILIATION", applicationId="CRB_AFL_REQ", master=true)
#PrimaryKeyFields(names={"CRB-TCRB_AFL_AFFILIATION-AFFILIATION_ID", "CRB-TCRB_AFL_AFFILIATION-AFFIL_SEQ" })
public class Affiliation{
}
When I try to get the annotations with this code:
FisaEntity entityAnnotation = (FisaEntity)klass.getAnnotation(FisaEntity.class);
And my test run this:
Affiliation affiliation = spy(new Affiliation());
Debugging my code, I can see my variable klass is:
com.req.model.Affiliation$$EnhancerByMockitoWithCGLIB$$123#123
Do anyone know any hack?
You answered your question yourself:
com.req.model.Affiliation$$EnhancerByMockitoWithCGLIB$$123#123
Simply don't make any assumption on mocks or spies. Use them for what they are meant to be: "test stubs" that provide functionality (aka behavior) to you.
In other words: you create mocks so that you can control/verify method calls made on these objects. You somehow inject the mocks into your code under test to get to the effects you intend to cause/observe.
Anything beyond that, like "hoping" that the class created by Mockito to do its magic has all the same annotations and whatnot of the original class: simply not a good approach.
As said: you are mocking objects to control their behavior, not the structural composition of the corresponding class that Mockito has to generate in order to instantiate the mocked objects.
Class clazz = Affiliation.class;
Annotation[] annotations = clazz.getAnnotations();
Annotation annotation = clazz.getAnnotation(Component.class);
These both should give you all the annotations of the class and the particular annotation of the class.
From your question, it is not clear what klass is!
If the purpose of your testing is solely to test that the annotation exists, then this way you can get the annotation(s) and then assert them...

Mockito and final equals() method in class - is it mockable?

I want to mock a class from other library using Mockito. I read that Mockito relies on specific (CGLIB provided I think) implementation of equals method. Unfortunately this outer class has equals() denoted with final modifier, and there is throwing exception in its body.
When I try to mock this class I always get exception from this method. CGLIB apparently doesn't get by with final, and real method is called.
Any ideas? What can I do, to mock this class using Mockito? Maybe other library will handle it?
[EDIT] quick explanation: I don't want to mock equals(), I check other methods. Problem is that mockito internally uses equals(), I don't know what for. As equals() is final, real method is called with exception throwing. I had hope that there is some setting in mockito "don't use equals()" :-)
Thanks for answers, I will read them closely tomorrow.
This matrix shows features supported by different frameworks:
External link to the matrix here.
According to this, only PowerMock and JMockit can mock final methods.
Mockito cannot mock final methods. Apparently PowerMock can though.
A hacky workaround could be to create a non-final method that delegates to the final equals method and mock that.
I believe that the steps to mock a final method with PowerMock and Mockito API would be: run your tests with the #RunWith(PowerMockRunner.class) then prepare the class you want to mock #PrepareForTest(ClassToBeMocked.class). After that, mock your object and use the when method to mock the equals method.
I think that it won't work if you do not use the PrepareForTest annotation in your test class.

How to mock object construction?

Is there a way to mock object construction using JMock in Java?
For example, if I have a method as such:
public Object createObject(String objectType) {
if(objectType.equals("Integer") {
return new Integer();
} else if (objectType.equals("String") {
return new String();
}
}
...is there a way to mock out the expectation of the object construction in a test method?
I'd like to be able to place expectations that certain constructors are being called, rather than having an extra bit of code to check the type (as it won't always be as convoluted and simple as my example).
So instead of:
assertTrue(a.createObject() instanceof Integer);
I could have an expectation of the certain constructor being called. Just to make it a bit cleaner, and express what is actually being tested in a more readable way.
Please excuse the simple example, the actual problem I'm working on is a bit more complicated, but having the expectation would simplify it.
For a bit more background:
I have a simple factory method, which creates wrapper objects. The objects being wrapped can require parameters which are difficult to obtain in a test class (it's pre-existing code), so it is difficult to construct them.
Perhaps closer to what I'm actually looking for is: is there a way to mock an entire class (using CGLib) in one fell swoop, without specifying every method to stub out?
So the mock is being wrapped in a constructor, so obviously methods can be called on it, is JMock capable of dynamically mocking out each method?
My guess is no, as that would be pretty complicated. But knowing I'm barking up the wrong tree is valuable too :-)
The only thing I can think of is to have the create method on at factory object, which you would than mock.
But in terms of mocking a constructor call, no. Mock objects presuppose the existence of the object, whereas a constructor presuppose that the object doesn't exist. At least in java where allocation and initialization happen together.
jmockit can do this.
See my answer in https://stackoverflow.com/questions/22697#93675
Alas, I think I'm guilty of asking the wrong question.
The simple factory I was trying to test looked something like:
public Wrapper wrapObject(Object toWrap) {
if(toWrap instanceof ClassA) {
return new Wrapper((ClassA) toWrap);
} else if (toWrap instanceof ClassB) {
return new Wrapper((ClassB) toWrap);
} // etc
else {
return null;
}
}
I was asking the question how to find if "new ClassAWrapper( )" was called because the object toWrap was hard to obtain in an isolated test. And the wrapper (if it can even be called that) is kind of weird as it uses the same class to wrap different objects, just uses different constructors[1]. I suspect that if I had asked the question a bit better, I would have quickly received the answer:
"You should mock Object toWrap to match the instances you're testing for in different test methods, and inspect the resulting Wrapper object to find the correct type is returned... and hope you're lucky enough that you don't have to mock out the world to create the different instances ;-)"
I now have an okay solution to the immediate problem, thanks!
[1] opening up the question of whether this should be refactored is well out of the scope of my current problem :-)
Are you familiar with Dependency Injection?
If no, then you ceartanly would benefit from learning about that concept. I guess the good-old Inversion of Control Containers and the Dependency Injection pattern by Martin Fowler will serve as a good introduction.
With Dependency Injection (DI), you would have a DI container object, that is able to create all kinds of classes for you. Then your object would make use of the DI container to instanciate classes and you would mock the DI container to test that the class creates instances of expected classes.
Dependency Injection or Inversion of Control.
Alternatively, use the Abstract Factory design pattern for all the objects that you create. When you are in Unit Test mode, inject an Testing Factory which will tell you what are you creating, then include the assertion code in the Testing Factory to check the results (inversion of control).
To leave your code as clean as possible create an internal protected interface, implement the interface (your factory) with the production code as an internal class. Add a static variable type of your interface initialized to your default factory. Add static setter for the factory and you are done.
In your test code (must be in the same package, otherwise the internal interface must be public), create an anonymous or internal class with the assertion code and the test code. Then in your test, initialize the target class, assign (inject) the test factory, and run the methods of your target class.
I hope there is none.
Mocks are supposed to mock interfaces, which have no constructors... just methods.
Something seems to be amiss in your approach to testing here. Any reason why you need to test that explicit constructors are being called ?
Asserting the type of returned object seems okay for testing factory implementations. Treat createObject as a blackbox.. examine what it returns but dont micromanage how it does it. No one likes that :)
Update on the Update: Ouch! Desperate measures for desperate times eh? I'd be surprised if JMock allows that... as I said it works on interfaces.. not concrete types.
So
Either try and expend some effort on getting those pesky input objects 'instantiable' under the test harness. Go Bottom up in your approach.
If that is infeasible, manually test it out with breakpoints (I know it sucks). Then stick a "Touch it at your own risk" comment in a visible zone in the source file and move ahead. Fight another day.

Categories