What is the simplest way to stub a complex interface in Java? - java

My code takes an interface as input but only excercises a couple of the interface's methods (often, just getters).
When testing the code, I'd love to define an anonymous inner class that returns the test data. But what do I do about all the other methods that the interface requires?
I could use my IDE to auto-generate a stub for the interface but that seems fairly code-heavy.
What is the easiest way to stub the two methods I care about and none of the methods I don't?

If you are using JUnit to test, use Mocks instead of stubs.
Read Martin Fowler's seminal article "Mocks Aren't Stubs"
I recommend the EasyMock framework, it works like a charm automatically Mocking your interface using reflection. It is a bit more advanced than the code samples in Fowler's article, especially when you use the unitils library to wrap EasyMock, so the syntax will be much simpler than that in the article. Also, if you don't have an interface, but you want to mock a concrete class, EasyMock has a class extension.

Check out JMock.
http://www.jmock.org/

Write an "Adapter Class" and overwrite only the methods you care.
class MyAdapter extends MyClass {
public void A() {
}
...
}

I believe the classical way is to make an abstract class with empty methods.
At least, that's how Sun did for MouseListener, creating MouseAdapter to ease the use of these events.

EasyMock or JMock are definitely the winners. I haven't used JMock, but I know with EasyMock you can setup the Mock object according to a testing script and it will return certain values in certain situations or points during your test. It's pretty easy to learn and get running, generally in less than an hour.

Related

Mockito a void method

How do I write a mockito test for the below method? IntReqDecorate.decorate adds an Id to a call.
public class IntVisitor implements Visitor {
private final IntReqDecorator intReqDecorator;
public InternalCallVisitor() {
this.intReqDecorator = new IntReqDecorator();
}
#Override
public void apply(Call call) {
intReqDecorator.decorate(call);
}
}
You're in a bit of a bind here. Your IntVisitor class is very tightly coupled to the concrete class IntReqDecorator. And the apply method is defined, verbatim, to do the same thing as intReqDecorator.decorate. So without changing any of the signatures, the best you can possibly do is write the same test you did for decorate but over again.
Now, what you probably should do with this code is break that dependency. First, your constructor concretely builds an IntReqDecorator the moment it's constructed. You can still do that as a handy default, but you should provide a way for the caller to specify the decorator they wish to use. We can do that by overloading the constructor.
public InternalCallVisitor() {
this(new IntReqDecorator());
}
public InternalCallVisitor(IntReqDecorator intReqDecorator) {
this.intReqDecorator = intReqDecorator;
}
Now this alone is enough firepower for us to write a good test. We can mock IntReqDecorator and use the one-argument constructor in tests.
But I would go even further. You only ever use one method from IntReqDecorator, namely decorate. But since it's a concrete class, it probably has other methods that we don't really need here. So in an effort to follow dependency inversion, it may be a good idea to create an interface IntReqDecoratorLike (choose a better name for your use case) that has just that one method, and then have IntReqDecorator implement that interface.
Then your constructor takes a IntReqDecoratorLike that is capable of doing only exactly what we need it to. The great thing about this is that you barely even have to mock anything to test it. You could theoretically just write a new (ordinary) class that implements IntReqDecoratorLike and use that in tests. We'll probably still use the mocking framework, since it does provide good error messages and built-in validation, but the alternative is there in principle.
As a very broad general rule, when you find yourself scratching your head and saying "This code looks difficult to test", you should take a step back. Because oftentimes, you can make a change to the API that not only makes testing easier but also makes the code more ergonomic to use down the road.

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

Changing private methods to protected for testing

Is it a good idea to change the private methods to protected for JUNIT testing.?
It's sometimes useful, yes.
If the class is extendable, make sure to make the method final.
Also, document the fact that the method is not supposed to be called by subclasses or external classes of the same package.
I use the Guava #VisibleForTesting annotation to make it clear that the method should in fact be private.
No in general not. The idea of unit testing is to test ... units. Or in other words implementations of interface methods.
If you want to test a method which you can't "see" this could be a code smell. Maybe you haven't separated your business logic enough from the UI code or something.
So the best idea would be to rethink your architecture. But if the alternative would be to not test your code it is a good idea to make those methods protected.
You can make the methods package local instead.
You can call private method using reflection, or you can decide that private methods shouldn't be tested directly, only indirectly.
Although you should prefer to refactor as #user714965 suggested, PowerMock's MockPrivate can do the mocking without opening the visibility of your private methods.
Writing your tests first usually leads to a design where you don't need to mock private methods.

PowerMock + Mockito VS Mockito alone

Can anyone please summarize, what exactly features gives you adding PowerMock on top of the Mockito?
So far I've found these:
mock static, final and private methods
remove static initializers
allow mocking without dependency injection - this one isn't clear to me. Can you elaborate?
Does it add anything else? Can you please sum up in several lines?
And do I need to sacrifice something when using PowerMock?
I don't know of other benefits offhand, but I want to address 2 of your sub-questions (and this is way too long for a comment):
allow mocking without dependency injection - this one isn't clear to me. Can you elaborate?
I think this came from the Motivation wiki page where they describe a way of refactoring code to not invoke static methods to make it testable. For a concrete example of what I think they're getting at, let's say you have this code and you want to test the method mocking the behaviour of the static method, without using powermock:
public class MyClass {
public void doGetString() {
...
OtherClass.getString(); //It's complex and scary and needs mocking!
...
}
}
One solution, would be to pull the static invocation into its own object, then inject an object that can be mocked come test time. For example, without using other frameworks, this could look like:
public class MyClass {
public static class StringGetter {
public getString() {
return OtherClass.getString();
}
}
private final StringGetter getter;
//Existing Constructor
public MyClass() {
this(new StringGetter());
}
//DI Constructor
MyClass(StringGetter getter) {
this.getter = getter;
}
public void doGetString() {
...
getter.getString();
...
}
}
I've seperated the behaviour of my method from the behaviour of the static invocation, and can use the DI constructor to inject mocks easily at test time. Of course with powermock I could just mock the static method in place, and run with it.
And do I need to sacrifice something when using PowerMock?
Physically no, but I'd say philosophically yes :). The below are my opinions, and I try to give good reasons behind them, but of course they are opinions so take them with a grain of salt:
The potentially scary thing that is happening with PowerMock is that in order to accomplish the feats of mocking private and static methods, they are using a custom class loader (which shouldn't be present at runtime in production) and changing the bytecode of your classes. Arguably, this should not matter with the vast majority of classes most of the time, but if you think about it, if the bytecode has changed, and certain side effects are no longer present, you're effectively testing different Classes albiet based upon your existing Classes. Yes this is a very academic argument.
You can somewhat mitigate this first argument by having good comprehensive integration and higher level tests that don't use PowerMock. In this way you can be more confident in the behaviours of your objects even if your unit tests are using PowerMock.
The other argument I have against PowerMock, is that it could almost too easily become a crutch. I agree that PowerMock can help with testing code that uses legacy code and other code that you do not have control over. However I would argue that when you have control over the classes that you need to mock, you should avoid its use. If you write a class with a private method or static method that you need to explicitly mock in order to test other methods, my gut instinct would say that this method may be doing too much and should be refactored and broken up. Having PowerMock already available in a project, you may be tempted to just mock it and move on, which would mitigate the pain that should encourage you to refactor the same. Yes there are sometimes due to various technical and non-technical constraints this is not possible, but it's good to solve pain points instead of avoid them :)
PowerMock is an extension to Mockito that allows mocking of static methods, constructors, final classes and methods, private methods, removal of static initializers and more.
Another feature of the Powermock mockito extension is that it supports mocking and stubbing of equals and hashcode.
As with all powermock features to be used with care, but adding (value-based) equality for specific results can be helpful.
One more feature of PowerMock is that we can mock construction of new objects in a method. It is helpful when we cannot change the code of the method to be tested.
For mocking final class we can use org.mockito.plugins.MockMaker. What you would need to do is
Create a folder in your test/resource folder with namemockito-extensions.
Create a file under it with the name org.mockito.plugins.MockMaker.
In that file have just one line mock-maker-inline
This will not require you to do add any new library and hence save some runtime.

Java Unit tests on methods that use third parties libs that don't use Interfaces

I'd like to know how do you test your methods if the libs you are using don't use Interfaces
My class is like
private ThirdParyClass thirdPartyClass;
void myMethod() {
AnotherThirdPartyClass param = "abc";
...
thirdPartyClass.execute(param);
}
I want to test that execute is called with the "abc" param.
I was thinking in creating MyInterface with an implementation that wraps the ThirdPartyClass and then change the class attribute to refer MyInterface. Quite boring stuff but I don't see any other way to be able to successfully test my class.
If ThirdParyClass was an Interface I could mock it, but in this case how do you procede?
i do not know which mock implementation you use it. But EasyMock has an extension available at the EasyMock home page that generate mock Objects for classes. See your mock implementation whether it does not support mock Objects for classes.
regards,
You can use JMockit. It goes far beyond what is possible with EasyMock Class Extension or with jMock and its ClassImposteriser. You actually get all the power of AspectJ, but with a much easier to use, mocking-specific, API.
As long as the third party class you're using isn't final and you don't need to mock final methods you can use JMock and the ClassImposteriser to mock it and carry on as normal.
private Mockery context = new Mockery() {{
setImposteriser(ClassImposteriser.INSTANCE);
}};
AnotherThirdPartyClass mockThirdParty = context.mock(AnotherThirdPartyClass.class);
Note you'll need to add some additional dependencies (jmock-legacy-2.5.1.jar, cglib-nodep-2.1_3.jar and objenesis-1.0.jar)
Why not just use AspectJ (AOP) for the unit testing.
By using an around aspect you can then control what gets passed into the method and better monitor it.
If you need to have it extend an interface, you can modify the class through aspects to give it more functionality, such as turning logging on/off or getting performance information.
Then, when you are done, you remove the aspects before putting this into production by just not including the aspect class files in the build.

Categories