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

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...

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();

what is the advantage of using #VisibleForTesting? [duplicate]

This question already has answers here:
How do I test a class that has private methods, fields or inner classes?
(58 answers)
Closed 5 years ago.
Who has a solution for that common need.
I have a class in my application.
some methods are public, as they are part of the api,
and some are private, as they for internal use of making the internal flow more readable
now, say I want to write a unit test, or more like an integration test, which will be located in a different package, which will be allowed to call this method, BUT, I want that normal calling to this method will not be allowed if you try to call it from classes of the application itself
so, I was thinking about something like that
public class MyClass {
public void somePublicMethod() {
....
}
#PublicForTests
private void somePrivateMethod() {
....
}
}
The annotation above will mark the private method as "public for tests"
which means, that compilation and runtime will be allowed for any class which is under the test... package , while compilation and\or runtime will fail for any class which is not under the test package.
any thoughts?
is there an annotation like this?
is there a better way to do this?
it seems that the more unit tests you write, to more your inforced to break your encapsulation...
The common way is to make the private method protected or package-private and to put the unit test for this method in the same package as the class under test.
Guava has a #VisibleForTesting annotation, but it's only for documentation purposes.
If your test coverage is good on all the public method inside the tested class, the privates methods called by the public one will be automatically tested since you will assert all the possible case.
The JUnit Doc says:
Testing private methods may be an indication that those methods should be moved into another class to promote reusability.
But if you must...
If you are using JDK 1.3 or higher, you can use reflection to subvert the access control mechanism with the aid of the PrivilegedAccessor. For details on how to use it, read this article.
Consider using interfaces to expose the API methods, using factories or DI to publish the objects so the consumers know them only by the interface. The interface describes the published API. That way you can make whatever you want public on the implementation objects and the consumers of them see only those methods exposed through the interface.
dp4j has what you need. Essentially all you have to do is add dp4j to your classpath and whenever a method annotated with #Test (JUnit's annotation) calls a method that's private it will work (dp4j will inject the required reflection at compile-time). You may also use dp4j's #TestPrivates annotation to be more explicit.
If you insist on also annotating your private methods you may use Google's #VisibleForTesting annotation.
An article on Testing Private Methods lays out some approaches to testing private code. using reflection puts extra burden on the programmer to remember if refactoring is done, the strings aren't automatically changed, but I think it's the cleanest approach.
Or you can extract this method to some strategy object. In this case you can easily test extracted class and don't make method public or some magic with reflection/bytecode.
Okay, so here we have two things that are being mixed. First thing, is when you need to mark something to be used only on test, which I agree with #JB Nizet, using the guava annotation would be good.
A different thing, is to test private methods. Why should you test private methods from the outside? I mean.. You should be able to test the object by their public methods, and at the end that its behavior. At least, that we are doing and trying to teach to junior developers, that always try to test private methods (as a good practice).
I am not aware of any such annotation, however the following may be of value: unit testing private methods
or the following: JMockit
You can't do this, since then how could you even compile your tests? The compiler won't take the annotation into account.
There are two general approaches to this
The first is to use reflection to access the methods anyway
The second is to use package-private instead of private, then have your tests in the same package (but in a different module). They will essentially be private to other code, but your tests will still be able to access them.
Of course, if you do black-box testing, you shouldn't be accessing the private members anyway.
We recently released a library that helps a lot to access private fields, methods and inner classes through reflection : BoundBox
For a class like
public class Outer {
private static class Inner {
private int foo() {return 2;}
}
}
It provides a syntax like :
Outer outer = new Outer();
Object inner = BoundBoxOfOuter.boundBox_new_Inner();
new BoundBoxOfOuter.BoundBoxOfInner(inner).foo();
The only thing you have to do to create the BoundBox class is to write #BoundBox(boundClass=Outer.class) and the BoundBoxOfOuter class will be instantly generated.
As much as I know there is no annotation like this. The best way is to use reflection as some of the others suggested. Look at this post:
How do I test a class that has private methods, fields or inner classes?
You should only watch out on testing the exception outcome of the method. For example: if u expect an IllegalArgumentException, but instead you'll get "null" (Class:java.lang.reflect.InvocationTargetException).
A colegue of mine proposed using the powermock framework for these situations, but I haven't tested it yet, so no idea what exactly it can do. Although I have used the Mockito framework that it is based upon and thats a good framework too (but I think doesn't solve the private method exception issue).
It's a great idea though having the #PublicForTests annotation.
Cheers!
I just put the test in the class itself by making it an inner class:
https://rogerkeays.com/how-to-unit-test-private-methods

Mocking a non-abstract method of an abstract class

I am trying to unit-test a class that extends an abstract base class.
Here are the "similar classes" for illustration purposes:
public abstract class MyAbstractBaseClass {
#Autowired
private WaterFilter waterFilter;
protected List<String> filterComponents(List<String> allComponents) {
return waterFilter.filter(allComponents);
}
}
public class MyDerivedClass extends MyAbstractBaseClass {
public List<String> filterWater(List<String> allWaterComponents) {
List<String> filteredComponents = this.filterComponents(allWaterComponents); //calls abstract class's filterComponets()
filteredComponents.add("something-else");
return filteredComponents;
}
}
Here is the unit test I am trying:
#RunWith(EasyMockRunner.class)
public class MyDerivedClassTest {
#TestSubject
private MyDerivedClassTest SUT;
#Before
public void setup() {
SUT = new MyDerivedClassTest();
}
#Test
public void test filterWater_HappyCase() {
//I want to mock my abstract class's filterComponents() method
//I am trying this:
EasyMock.expect(SUT.filterComponents(getDummyComponents())).andReturn(getSomeComponents());
//What to replay here?
//EasyMock.replay(...)
List<String> actualResult = SUT.filterWater(getDummyComponents());
//assert something
//What to verify?
//EasyMock.verify(...)
}
}
When I run this test, I get
java.lang.NullPointerException
in MyAbstractBaseClass.filter(allComponents)
I understand that the autowired "waterFilter" is not getting initialized. But then, I just want to mock the "non-abstract" method of the abstract class in my unit test.
How should I go about this using EasyMock? Also, I don't know what to replay() and verify().
When you write an unit test, you test a object (generally, a method of it) and you may mock a object (generally, a method of it).
However, you should not unit test and mock the same object because in a some way, it seems not very natural : if you test a method of a class, the behavior of the tested class should stay as natural as possible and not fake its own methods.
Otherwise, we can wonder if the quality of the unit test is good.
Why ? Because it doesn't reflect the real behavior of the class that we would have at the runtime, but just some part of its behavior.
In a unit test, isolation is researched but behind it, the idea is to isolate your under test class only from the other classes and not an isolation of its own behavior.
Of course, you can try to mock a no-abstract method in the abstract class of your under tested class but the design and the quality of your test may become less good.
In your case, I imagine two reasons to mock the no-abstract method in the abstract class :
the waterFilter field dependency annoys you because it is not valued, so an exception (NullPointerException) is raised during the test.
You really want to mock the no abstract method in the abstract class because you have already unitary tested this method and you don't want to duplicate this test.
1) If your the problem is the waterFilter field dependency.
you should mock the waterFilter field. To mock a field, it must be accessible and modifiable. In your case, it's not straight because the field is private.
So, you have two ways to access to it to be able to mock it :
change your design to give the possibility to set the field from a public method or in the constructor of MyDerivedClass.
use reflection to set the field (use an API or do it yourself because it's not hard).
You don't need to do verify operations with EasyMock. Just mock the result returned by waterFilter.filter(allComponents) such as :
waterFilterMock.filter(mockedComponents)
In this way, the mock returns the value you have chosen and in your JUnit assertion, you are able to do the correct assertion for your method under test.
Just for information, you could use Mockito instead of EasyMock. It's more flexible and it offers more readable operations.
For example, you could do it with Mockito :
Mockito.when(waterFilterMock.filter()).thenReturn(mockedComponents);
As you can see, it is more readable.
2) If you problem is that you really want to mock the no-abstract method in the abstract class because you have already unitary tested it
You should modify your design and use composition instead of inheritance. You would have not MyAbstractBaseClass any longer but simply a dependency between two classes (the one has a field of the other). In this way, you could mock the filterComponents() method in a natural way.
Expectations has to be set on mocked resources.
In your case i think you should inject a mocked instance of WaterFilter.
And your expectation,replay and verify should be set on waterFilter object instance.
You can refer to the example provided in given below link.
http://www.tutorialspoint.com/easymock/easymock_junit_integration.htm

Getting around setter injection using mockito's #InjectMocks

I have an abstract class with two Map fields. One I would like to mock and inject into an object of a subclass of AbstractClass for unit testing. The other I really don't care much about, but it has a setter.
public abstract class AbstractClass {
private Map<String, Object> mapToMock;
private Map<String, Object> dontMockMe;
private void setDontMockMe(Map<String, Object> map) {
dontMockMe = map;
}
}
When using #InjectMocks, it automatically tries to inject in the order: constructor, setter, field. It checks if it can inject in each of these places by checking types, then names if there are multiple type possibilities. This doesn't work well for me, because my mocked mapToMock is actually injected into dontMockMe via its setter. I cannot edit this abstract class. Is there any way for me to get around the setter injection? Thank you in advance!
Well this is a corner case, where automatic injection won't work in the way Mockito injection is currently designed. Also Mockito suffer from some shortcomings when there is multiple fields with the same types.
So to understand why this doesn't work let's dive a bit in the way Mockito performs injection :
It will try to inject dependencies via constructor injection, if it successes it won't try the following steps in order to protect the newly created instance from eventual side effects.
Then if constructor injection did not happen (no arg constructor, or object already instantiated), then Mockito will look for matches between mocks and setters. But it has to make some choices for it to happen automatically.
If there is only mock of type A and only one setter with type A then setter injection will happen.
If there is either multiple mocks or setters of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
Then if there is still some mocks left for injection, field injection might happen, using the same algorithm as with setter :
If there is only mock of type A and only one field with type A then field injection will happen.
If there is either multiple mocks or field of type A it will try to find match using the type and the name of the mock (usually the #Mock field name). If matches are found then injection will happen.
At the moment your code is stuck at stage 2.1 because there is probably only one mock available.
That being said with the current implementation of Mockito there is no real elegant solution, it is necessary to write yourself the injection code. And that is actually the wanted point with Mockito injection, if injection is too complex or weird, then you will have to write it out ; writing this boilerplate code is actually the best tool to question the current design.
Mockito injection is really designed for simple, straight designs.
In my opinion, I find wrong :
to mock a Map, a type you don't own, that might cause many problems.
to mock only a single map in tested object, that means your test knows too much about the inner working of the tested object.
It would benefit the design if you refactor the code and make the collaborators emerge. With clear dependencies/collaborators it will most certainly make the injection clearer too. Also the test should focus on asserting the interactions with the collaborators not how data how the implementation is done, data should only be tested as a result to a given input.

mocking class with annotated methods

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.

Categories