Tuesday, May 25, 2010

How to partially mock a class and its private methods using PowerMock

Earlier, in the how-to series we had seen how-to mock constructors.  In this post we will have a look at how-to partially mock classes and even their private methods using PowerMocks - Mocks on Steroids!

Lets first look at the code to test before I start with my rambling

Code under test:

We want to write a test case to test method1 of ServiceA class.  ServiceA's method1 invokes method2.  method2 performs some complicated business logic - in this case creates an instance of ServiceB and invoked doBusinessOperation on that instance.

There are two approaches to test ServiceA's method1.


  • Write the test case to mock out the ServiceB's constructor and assert that doBusinessOperation method was invoked on the mocked ServiceB object.
  • Stub the method2 call!  Only verify that from method1 a call was made to the method2.

We already know how to write tests for the first approach.  Today we are more interested in looking at how do we write tests for the second approach.

Why would we ever choose the second approach over the first approach?  May be because method2 was already tested in some other test case.  Hence, we just want to make sure that method1 calls method2 with the right arguments.

So how do we partially mock ServiceA?

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

PowerMockito class provides a method called spy to create partial mock of a class.  This method takes an instance of the class that you want to partially mock as argument (in this case ServiceA).  Why? Because we want to invoke actual implementation of method1 and mock only method2.

Syntax

Then, we want to stubb out the method2 and return some dummy value.  This how its done

Notice the difference in the syntax then the regular when-theReturn syntax.  As, if we use the when-thenReturn syntax actual call to method2 will be made!  Why? Because PowerMocks does not know whether you are setting up an expectation on a partial mock or actually invoking the method.  Hence, be careful with partial mocks and choose the right syntax.

How to verify that the method was actually called?

No surprises here.

The full test case would look like:

A variation of the above example, what if the method2 was private?  Can we still stub it?  Of-course the right answer is YES!

Code under test:

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

Now, the above doReturn-when-method2 syntax wont work.  As method2 is private and is not accessible outside the scope of the class.  How do we stub it then?

Only change is, we pass in the name of the private method to stub as string argument to when method.  when method also accepts the var args array of arguments to the method2.

To verify that the private method2 was invoked use

Here also, instead of verify we use verifyPrivate and call a invoke method which accepts, name of the private method and its arguments.

Full test case would look like this:

Yes!  Thats it.  We have achieved what we intended to do!  PowerMock's is really a valuable tool to have in once arsenal!
Have some Fun!