Monday, June 28, 2010

How to suppress fields with PowerMock

Now why would you want to do that! Lets look at the code straightaway.

Code under test:

The AccountDAO class has a "session" field, which has been initialized where its declared. Assuming that Session class in our example, is a wrapper over the the Hibernate Session class which talks to the database and does stuff for us.

BTW I couldn't agree more that its a terrible design!

So, basically what we want is to suppress the field "session" and instead use a stubbed Session instance.   Which means, we would stub out the getSession method, to write good unit-test case for the findAccount method.

So how do we suppress the field "session"

How would we test it - How do they do it!

The suppress method (which we had a look in the earlier post) can not only suppress the methods but can also suppress fields.


The Syntax:

What does the above syntax mean? Just read the line in plain English and that is exactly what it means!

Suppress the field of AccountDAO class called "session"

After this statement if we call getSession on any instance of AccountDAO it will always return null.

Q: But how can PowerMock do it?
A: Via byte code manipulation.  Remember our old friend @PrepareForTest(AccountDAO.class) annotation.

So we have solved one part of the problem. The next problem is to return a stubbed session instance when getSession method of AccountDAO is called. How can we do that?
A: Remember partial mocks via the spy method

That makes the problem look much simpler right?

So lets look at the test code:

Yes! We have managed to suppress a field for any given class.

Really, PowerMock's (using the Mockito api) keeps dazzling us with its Power!

Monday, June 21, 2010

How to suppress static initializers using PowerMock

In my previous post we saw how we could test methods of class whose constructor does evil stuff.  What if the static initializer of the class does evil stuff?  How will we test such a class?
This is exactly what we are going to see in this post!

You might think why on earth would you want to do that? For a few very simple reasons like, legacy code, third party library, may be something else.

At times, we might have to use a third party library that does some weired stuff in static initializers. It might load a native library, may perform some IO operation, may open up a database connection etc.
When we are unit-testing a class that uses this third party class (whose static initializer does wired stuff), we simply don't want to deal with all this complication.

This is the reason why we might want to suppress the static initializer of a class.

Convinced about the "why"? Lets look at the "What" part.

Code under test:

Hmmm, looks like a familiar class?
We want to write a unit-test case for the AccountDAO class. In that we are interested in testing the findAccountById method. This method get a Hibernate session from HibernateUtils class and then invokes the get method on the session.

But look at how HibernateUtil class.  It initializes the static SessionFactory instance.  It does that in a static initializer!  Man! this means every time the unit-test case for AccountDAO is executed the sessionFactory will be created. We don't want that to happen do we?

Also notice that, for testing purpose I have a System.out.println line in the static initializer of HibernateUtil. If we are successfully able to suppress the static initializer of HibernateUtil we should not be getting any output on the console.

So how do we write unit-test for AccountDAO class without initializing the SessionFactory.  Lets look at the "How" part now.

How would we test it - How do they do it!

Turns out, as always, there is a very simple way to suppress the static initializers of any class using PowerMocks - Mocks on Steroids! 
We simply have to use an annotation called @SuppressStaticInitializationFor.  As the annotation reads it suppresses static initializer for a given class.  But which classes static initializer do we want to suppress?  How do we tell this to PowerMocks? Via passing the fully qualified class name to the @SuppressStaticInitializationFor annotation.

Here is the syntax

Please note that we are passing the fully qualified class name as string to the @SuppressStaticInitializationFor annotation.  Unlike in the case of @PrepareForTest annotation where, we pass the class reference like this

Can you tell me why this difference in the syntax? Well, for those who have not guess it, here's the answer:
Because if we pass the class reference like HibernateUtil.class then, by the time that statement executes the class is already loaded and static initializer would have already been executed. We don't want that.
Sole purpose of using the @SuppressStaticInitializationFor annotation was to suppress the static initializer of HibernateUtil class. And this is the reason we don't pass the class reference but we pass the fully qualified class name as string.
After a lot of explanation lets look at the complete test code

Thats it! We have managed to suppress the static initializer of a class.
Writing unit-tests with PowerMocks (Mockito api) is fun!
BTW the statement "The static initializer of HibernateUtil invoked" is never printed on the console. You will have to take my word for this! What? You don't trust me? Then, try the example on your own :)

Wednesday, June 16, 2010

How to test methods of a class whos constructor is evil, using PowerMock

As promised in my previous post, today I will show, the second way to write test cases for methods of a class whose constructor does crazy stuff.
Example of "crazy stuff" would include opening a db connection, load a native library etc. There are many things that would come under the "crazy" umbrella but lets not go there.

Code under test:

You remember our dear friend Mr. LegacyCustomer right? Yes this class has an evil constructor that does some crazy stuff, in our case it throws a RuntimeException. Effectively, this means we can never create an instance of this class, as there is not constructor that we could invoke.

One of the way to test the method getCreditLimit would be to suppress the constructor of LegacyCustomer using the suppress method which we have already seen in the previous post. So what is the other method to test it?

(On the side note, most Mocking framework don't even have one way to write test for the above code but PowerMock's has two ways in which we could test the above code! How awesome!)

How would we test it - How do they do it!

Turns out, there is a class called Whitebox in PowerMocks using which we could instantiate a class without invoking its constructor. Whitebox class has a lot of features to bypass encapsulation of a class but we will discuss those features later. Today lets focus only on instantiating the class and testing the getCreditLimit method.

To instantiate the class using Whitebox class we use the following syntax

The newInstance method on the Whitebox class takes the name of the class that has to be instantiated without calling the constructor.

Now writing the complete test case would be tad simple. Lets look at the complete test code

Note that we don't even need to use the @RunWith and @PrepareForTest annotations. Whitebox class can instantiate LegacyCustomer without even invoking the constructor.

Please note: If we had to write the test case using the suppress method we would have to use the @RunWith and @PrepareForTest annotations.

Life looks a lot better when we have powerful tools like PowerMock (with Mockito api) at hand!

Monday, June 7, 2010

How to supress methods and constructors using PowerMock

We have come a long way in our how-to series, demonstrating the power of PowerMocks (with the Mockito api).  I hope you are liking it as much as I like writing about it!

In the earlier post we saw how we could partly mock classes and its private methods using PowerMocks.  Today I will demonstrate how we could suppress a constructor and a method.

Now you must be thinking why the hell would I every want to do that!  Well believe me there are cases where you would want to do that :)  And we are about to have a look at one

Code under test:

Now you understand why we might need to suppress a constructor?  Well as we can see in the above code class LegacyCustomer's constructor simply throws RuntimeException (this is just a place holder.  In real world it might do some complicated operation may be loads a native library, establishes a connection to the db god knows what all it can do!).  Customer class extends LegacyCustomer class to add some more behavior to it (I am so making it up!).  In real life, I would never write such code.  Believe me!

But lets assume for now that we want to write a test case to verify that, when the Customer object is created it sets the email field to the value passed as argument.

So how do we test this?

How will we test it - How do they do it!:

We can easily suppress the constructor of LegacyCustomer class.
"Suppress a constructor" means that the code in the constructor will not be called and thats exactly what we want.  The syntax to do that is

Lets read the above line in English.
Suppress the constructor of LegacyCustomer class which takes one argument of String type.  Nice job!
This is step 1 of the process.

Now, if you think for a moment, base class constructor will be invoked automatically when derived class instance is created right!  Hence, in this case LegacyCustomer class's constructor will be invoked as soon as we create an instance of Customer class.

We dont want that to happen!
We want to suppress the call to the constructor of LegacyCustomer class.  So we will have to change the byte code of Customer class and tell it not to invoke the Constructor of LegacyCustomer class.

How do we do that?  Well, you know the answer to that using the following line of code

PowerMocks is happy to do the all byte code manipulation for us, we just need to tell it to do so.  This is done via our very own @PrepareForTest annotation.

So lets look at the entire test case

Simple?

Want more?

What if, I wanted to test a method in Customer class that actually invokes another method that does some complicated stuff?

Lets look at the code to test:

Well its basically the same code as above we have just added the getNetAssetValue method to the Customer class and we want to test this method.

How do we test it - How do they do it!

One way to do that is of-course by using spy and then stubbing the private method.

The other way is to suppress the call to doSomeComplexCalculation method.  What is the syntax for doing that?

Again, lets try to read the above syntax in English language.
Suppress the method of Customer class whose name is doSomeComplexCalculation
 Nice!

Lets look at the complete test case


That's all folks!

Looks like now we know how to suppress any constructor or a method!  Well, what if we wanted to test some method in LegacyCustomer class?  Remember the LegacyCustomer class constructor throws a RuntimeException.

Hummmm, that's interesting how can we suppress the constructor of class under test.  Turns out there are two ways of doing it.  One of the way is what we have just seen, using the suppress method.  Will show the other way in the next post.

Till then, Have Fun with PowerMocks!
Have some Fun!