Sometimes TDD requires a hammer

While there are myriad mocking libraries available for the Java platform, only a select few of these nifty frameworks is capable of mocking the non-mock-friendly modifiers of static and final. Static (or class) methods, while handy for factories, become a nuisance for a framework like Mockito, however, with the inclusion of PowerMock, you’ve got yourself a proverbial hammer.

As I wrote about previously, I had to deal with a 3rd party library that is used to integrate with a networked service. This library is essentially hardwired to interact with homebase, which naturally provides some challenges when trying to test ones code that relies on this library. Moreover, the said library contained a static method for creating instances of a specialized class, which, naturally, my code depended on.

PowerMock is made to work in concert with either EasyMock or Mockito; what’s more, it comes with a custom runner for inclusion in JUnit. I’m going to show you how to use PowerMock with Mockito as I happen to find Mockito’s syntax much more fluent than EasyMock’s.

For starters, you’ll need to use two class level annotations – @RunWith for specifying the PowerMockRunner class (this is a JUnit annotation) and another dubbed @PrepareForTest, which takes the class with static methods you wish to mock. @PrepareForTest is provided by PowerMock.

In my case, the class containing a static method is named QTP, accordingly; my test class looks like this:

JUnit test class with class level annotations
<span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<code class='java'><span class='line'><span class="nd">@RunWith</span><span class="o">(</span><span class="n">PowerMockRunner</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
</span><span class='line'><span class="nd">@PrepareForTest</span><span class="o">(</span><span class="n">QTP</span><span class="o">.</span><span class="na">class</span><span class="o">)</span>
</span><span class='line'><span class="kd">public</span> <span class="kd">class</span> <span class="nc">CreateCommandTest</span> <span class="o">{</span>
</span><span class='line'>  <span class="nd">@Test</span>
</span><span class='line'>  <span class="kd">public</span> <span class="kt">void</span> <span class="nf">testCreateRequest</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{}</span>
</span><span class='line'><span class="o">}</span>
</span></code>

Next, in your test method, you use PowerMokito’s mockStatic method, which takes the class (again) with static methods you wish to mock.

JUnit test case using PowerMock & Mockito
<span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<code class='java'><span class='line'><span class="nd">@Test</span>
</span><span class='line'><span class="kd">public</span> <span class="kt">void</span> <span class="nf">testCreateRequest</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
</span><span class='line'>  <span class="n">PowerMockito</span><span class="o">.</span><span class="na">mockStatic</span><span class="o">(</span><span class="n">QTP</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
</span><span class='line'>  <span class="c1">//....</span>
</span><span class='line'><span class="o">}</span>
</span></code>

You can then mock a static method on the class you’ve been passing around to mockStatic and the @PrepareForTest annotation like you would normally do with Mockito. For instance, I can use the when method to specify what I want to happen when this static method is invoked.

Using normal Mockito actions for mocking
<span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<code class='java'><span class='line'><span class="nd">@Test</span>
</span><span class='line'><span class="kd">public</span> <span class="kt">void</span> <span class="nf">testCreateRequest</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
</span><span class='line'>  <span class="n">PowerMockito</span><span class="o">.</span><span class="na">mockStatic</span><span class="o">(</span><span class="n">QTP</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
</span><span class='line'>  <span class="n">QTP</span> <span class="n">qtpThing</span> <span class="o">=</span> <span class="n">mock</span><span class="o">(</span><span class="n">QTP</span><span class="o">.</span><span class="na">class</span><span class="o">);</span> <span class="c1">//normal Mockito mocking</span>
</span><span class='line'>  <span class="c1">//QTP.create is static</span>
</span><span class='line'>  <span class="n">when</span><span class="o">(</span><span class="n">QTP</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="s">"dm2q"</span><span class="o">,</span> <span class="s">"0C4F7501UDC8C1EB43B06C988"</span><span class="o">)).</span><span class="na">thenReturn</span><span class="o">(</span><span class="n">qtpThing</span><span class="o">);</span>
</span><span class='line'>  <span class="c1">//QTP.createRecord isn't static</span>
</span><span class='line'>  <span class="n">when</span><span class="o">(</span><span class="n">qtpThing</span><span class="o">.</span><span class="na">createRecord</span><span class="o">(</span><span class="n">any</span><span class="o">(</span><span class="n">Tckt</span><span class="o">.</span><span class="na">class</span><span class="o">))).</span><span class="na">thenReturn</span><span class="o">(</span><span class="k">new</span> <span class="n">Long</span><span class="o">(</span><span class="mi">1000000L</span><span class="o">));</span>
</span><span class='line'>  <span class="c1">//...</span>
</span><span class='line'><span class="o">}</span>
</span></code>

Finally, you can use PowerMock to ensure your mocked static method is actually invoked. The requirements here are a bit funky; that is, it requires you first specify how many times with one line of code and then you actually call the static method.

Verifying your mocked static method was invoked
<span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<code class='java'><span class='line'><span class="nd">@Test</span>
</span><span class='line'><span class="kd">public</span> <span class="kt">void</span> <span class="nf">testCreateRequest</span><span class="o">()</span> <span class="kd">throws</span> <span class="n">Exception</span> <span class="o">{</span>
</span><span class='line'>  <span class="c1">//...</span>
</span><span class='line'>  <span class="n">PowerMockito</span><span class="o">.</span><span class="na">verifyStatic</span><span class="o">(</span><span class="n">Mockito</span><span class="o">.</span><span class="na">times</span><span class="o">(</span><span class="mi">1</span><span class="o">));</span>
</span><span class='line'>  <span class="n">QTP</span><span class="o">.</span><span class="na">create</span><span class="o">(</span><span class="s">"dm2q"</span><span class="o">,</span> <span class="s">"0C4F7501UDC8C1EB43B06C988"</span><span class="o">);</span>
</span><span class='line'>  <span class="c1">//...</span>
</span><span class='line'><span class="o">}</span>
</span></code>

Yeah, that’s sorta confusing, I know.

Nevertheless, as most people in the world of Java figured out long ago, static methods are somewhat difficult when it comes to testing. That is, while a method that conceptually has no state, at first glance, seems straightforward enough to test, the issues arise when that static method does something like hit a database or in my case, call a web service to a networked asset. There is no easy way to override such behavior (unless, of course, you pull out a hammer).

Static methods have a place. But when it comes to testing code, whether it be legacy or some 3rd party library, the static modifier requires a hammer and as I hope I’ve shown you, PowerMock is that hammer.

Related:
Notice to our Readers
We're now using social media to take your comments and feedback. Learn more about this here.