Up till now I have not come across that many projects that would truly conform to the principles of Test Driven Development. Once again, I found myself in an unenviable situation of introducing unit tests to a code which had been released to production a long time ago, completely untouched by any kind of test automation. My aim was to keep the tests simple, understandable and fast so that one could easily add more until the core business logic gets a sufficient test coverage without delaying the build time. Due to a high number of intrinsic dependencies it was a challenge to keep the tests on a unit level and not to resort to complex (and potentially much slower) integration tests. I decided to mock out most of the dependencies and stay focused to the tested classes only. Mockito helped me a great deal, though there were some pitfalls along the way. Going about static method calls was one of them. Today, I would like to a share my experience with PowerMock and static method stubbing. 

One of the tested methods produced a sorted list of values. Sorting was an essential part of the business logic. Here is a quick draft of how the implementation looked like:

class Foo {
  public List<String> getTheList() {..}
}  

class Bar {
  private Foo foo = new Foo();  

  public List<String> doSomethingClever() {
    List<String> theList = foo.getTheList();
    ..
    // do something clever
    ..
    // finally, return the sorted results
    Collections.sort(theList)
    return theList;
  }
}

With simplicity in mind I didn’t bother with looping over the list to see if the records were sorted as expected. Instead, I merely wanted to check that the list was passed as an argument to the static call of Collections.sort. Using PowerMock it only takes a few lines of code to accomplish this task:

..
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.doNothing;
import static org.powermock.api.mockito.PowerMockito.spy;
import static org.powermock.api.mockito.PowerMockito.verifyStatic;
..
@Test
public void recordsShouldBeSorted() {  

 // the list I expect to be sorted later on
 final List expectedList = new Foo().getTheList();  

 // letting PowerMock in
 spy(Collections.class);
 doNothing().when(Collections.class);  

 // confusing as it is, no sorting happens at this stage
 Collections.sort(expectedList)  

 // cool, now I am ready to check the list got sorted
 // without looking at the returned data  

 // let's invoke the tested method
 new Bar().doSomethingClever();  

 // time to verify the sorting was applied
 verifyStatic();  

 // once again a bit confusing
 // this time it checks the expected list
 // was passed as an argument to the sort call
 Collections.sort(expectedList);
}

Hope it makes sense. If not, here is the pattern from the framework’s point of view: 

  1. Tell me which class and which static method
  2. Call the business method invoking the static method we agreed on
  3. Let me check if the static method got called with expected arguments
Personally, I consider this a cool feature. Of course, all that magic doesn’t come completely for free and some extra arrangements are needed:
import org.junit.Test;import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;  

@RunWith(PowerMockRunner.class)
@PrepareForTest({Collections.class, Bar.class})
public void BarTest {  

@Test
public void recordsShouldBeSorted() {..}

That’s it. Originally, I overlooked the need to add the tested class (Bar in this example) to the PrepareForTest annotation. I was pulling my hair out when trying to understand why the heck the test wouldn’t pass even though debugging proved the sorting did happen. It took me way too long to spot that tiny but substantial mistake. I hope this post helps someone else to save a bit of their time.


Tomas Zezula

Hello! I'm a technology enthusiast with a knack for solving problems and a passion for making complex concepts accessible. My journey spans across software development, project management, and technical writing. I specialise in transforming rough sketches of ideas to fully launched products, all the while breaking down complex processes into understandable language. I believe a well-designed software development process is key to driving business growth. My focus as a leader and technical writer aims to bridge the tech-business divide, ensuring that intricate concepts are available and understandable to all. As a consultant, I'm eager to bring my versatile skills and extensive experience to help businesses navigate their software integration needs. Whether you're seeking bespoke software solutions, well-coordinated product launches, or easily digestible tech content, I'm here to make it happen. Ready to turn your vision into reality? Let's connect and explore the possibilities together.