Introduction
This article is not another diatribe to tell you the importance of unit testing. I think we can all agree that it is important. This is about solving an issue that comes up frequently in unit testing. How do I test static methods, and how do you test private methods.Until PowerMock, most developers were told you can't really test a static method per se. I will show how to do it below.
A common mechanism for testing private methods is to change them to protected. This is not a good solution for a number of reasons. So how do we test them? Again, PowerMock has come to the rescue.
I want solutions. I use Arquillian, but I am not such a zealot that I will chant the mantra that mocking is evil and should not be done. It is a means to an end. That being said, we use Mockito which in my professional experience is the best current mocking framework available. It is easy to setup and use.
However, Mockito has its limitations. Two are mentioned above. The fine developers of PowerMock have come up with an additional framework to use in conjunction with Mockito to get around the limitations.
Solution
The Apache Maven sample code for the project was developed using NetBeans and can be found on Bitbucket here: unit-testing-mockito-powermockito.Since I am a Apache Maven user, I simply add the relevant frameworks to my
pom.xml
as shown below:
Once the test frameworks are in place, I can use the PowerMockRunner
to help me with my testing. The following are some simple classes to demonstrate how to test. The first is a class to generate UUID values for IDs.
IdentityUtilities.java
Next, I need a class to represent a person. I am interested in testing the private method
generateId
.
Person.java
Finally, we need our
PersonTest
class to test our Person
object. The explanation follows the code.
PersonTest.java
The
@RunWith(PowerMockRunner.class)
annotation tells jUnit that we are using an extension to handle testing of this class. This tells jUnit to use this test runner instead of its own test runner.
The
@PrepareForTest({IdentityUtilities.class, Person.class})
serves multiple purposes here. The first is to tell PowerMock that we need to do some preparation of the classes to instrument them for our testing. Classes defined using this annotation are typically those that needs to be byte-code manipulated. This includes final classes, classes with final, private, static or native methods that should be mocked and also classes that should be return a mock object upon instantiation. IdentityUtilities.class
is our class with a static method, and Person.class
contains our private method.
The first test
testInitialize()
behaves like any other Mockito test with the exception that we mock it using PowerMockito.mockStatic(IdentityUtilities.class)
to initialize it. This makes testing static methods as easy as any other Mockito test.
The second test requires a little more explanation. In this case, we spy on the object we are creating. This allows us to instrument it. Then using the "spied" instance we use
PowerMockito.when(instance, "generateId").thenReturn("UNIT-1A")
to tell the framework that when the private method "generateId" is called, we want to return a specific value. Then we initialize the instance, and check the value is what we expected. Finally, we can optionally check to make sure that the method was actually called by using verifyPrivate(instance).invoke("generateId")
.
No comments:
Post a Comment