Showing posts with label final class. Show all posts
Showing posts with label final class. Show all posts

Tuesday, May 11, 2010

Testing the Untestable code using PowerMock (Mockito api)

Taking inspiration from this excellent post by Johan Haleby, today I am going to jump a few gears and show you the real power of PowerMocks.  I will show you how can we write good unit-tests to test the untestable code!

We will continue the How-To series using PowerMocks (Mockito api) but today lets look at something more complicated.

You must be thinking, if the code is untestable then how can we write unit-tests?  But, that my friend is the real power of PowerMocks, we can write unit-tests for testing untestable code as well!

So What are we testing today.

Code to Test:

The code example is taken from one of the code samples of JMockit unit-testing framework (which by the way is another powerful unit-testing framework).  At first glance the code might not look as complicated, but make a note of the following points and then think how will you ever write a unit-test for doBusinessOperationXyz method?

  • The ServiceA class is final
  • It invokes a static method on Database class called find which returns a list
  • It then creates a new instance of ServiceB class and invokes computeTotal method, passing it items retrieved from Database.find call
  • ServiceB class is final as well
  • Invokes another static method on Database class called save, passing it the EntityX instance

Wow! it seems like a really tough class to test.  Lets move ahead and write some good unit-tests to test the above code!

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

You will be surprised to know that, we could write multiple unit-tests for the above code depending on what exactly we want to test!  How awesome!

Test Requirement 1:

Lets say we want to test that, the ServiceB was invoked to compute total.

Test Code:

As usual we have to annotate the TestCase with @RunWith annotation (go here know more on why we have to do so).

We can verify that computeTotal method was invoked on ServiceB instance via a mocked ServiceB object. But if you think about this for a moment, how can we do that?  Because ServiceA's doBusinessOperationXyz is actually instantiating ServiceB.

How can we suppress this behavior and inject our mocked ServiceB object?  Simple! via byte-code manipulation of ServiceA class :)

No no, don't worry, we don't have to do byte-code manipulation on our own, PowerMocks does that for us.  All we need to tell PowerMocks is for which classes we want to perform byte-code manipulation using the @PrepareForTest annotation (go here to know more about @PrepareForTest annotation).

Another point is we want to mock static methods in Database class as well.  Hence we have to use @PrepareForTest annotation for Database class as well.

And finally, note that since we want to mock ServiceB class, which is a final class we have to use @PrepareForTest annotation for ServiceB class as well.

Enough fluff, show me the stuff!

The unit-test code looks like this

Thats all folks!  We have successfully tested the Untestable code for our first requirement


Thats all folks!  We have successfully tested the Untestable code for our first requirement

Test Requirement 2:

Lets say we want to test that, the Database was used to save EntityX.

Test Code:

Now that you have read the post so far, this one must look straightforward to you!

The test-case looks like

Thats it!

Test Requirement 3:

Database find was invoked to get the list of EntityY

Test Code:

The test-case looks a lot similar to the previous example

I promise its not much after this.

Test Requirement 4:

Should verify that EntityY list returned from Database.find was used to computeTotal

Test Code:

This is the final one.

Test Requirement 5:

Should verify that computed total was set on EntityX instance

Test code:

Done!  Its pretty evident from the above examples that testing the Untestable code is pretty easy using PowerMocks (Mockito api)

Feedback, questions and comments are welcome as usual!

Monday, May 10, 2010

How to mock final methods and classes using PowerMock

This is the second post in the how-to series of using PowerMockito to write beautiful unit-tests. In my previous post we saw how can we write unit-tests for mocking static methods.

Today, I will demostrate how we can mock final class and final methods using PowerMocks (Mockito api) - Mocks on steroids!

Requirement:

I am going to take a ficticious example, were AnotherService class's invokeFinal() method invokes a final method on the instance of FinalService class which is a final class.

Code under test:

The final method doSomething in the final Class FinalService does nothing, just throws an exception.  AnotherService's invokeFinalMethod invokes doSomething method.

Most common mocking framework in the java world cannot mock final classes/methods because they are typically based on creating proxies.  Creating proxies for final classes is not possible as we cannot subclass a final classes.

So how we do we it in PowerMocks (Mockito api)?

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

Aha! Its tad simple.  We don't need to do anything special here.

We have to use @PrepareForTest annotation with FinalService so that PowerMocks can actually mock FinalService (Go Here for explanation on @PrepareForTest).  Next up, we need to create the stub of FinalService using the following code

Then, we have two approaches

I will show both the approaches

State based testing:

Interaction based testing:

Thats it!

It is needless to say that things look pretty easy with PowerMocks (Mockito api).  They look easy because they are easy with PowerMocks!  Yes! you can with PowerMocks (Mockito api)!

Feedback, questions and comments are always welcome.
Have some Fun!