Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

We are trying to design our system to be testable and in most parts developed using TDD. Currently we are trying to solve the following problem:

In various places it is necessary for us to use static helper methods like ImageIO and URLEncoder (both standard Java API) and various other libraries that consist mostly of static methods (like the Apache Commons libraries). But it is extremely difficult to test those methods that use such static helper classes.

I have several ideas for solving this problem:

  1. Use a mock framework that can mock static classes (like PowerMock). This may be the simplest solution but somehow feels like giving up.
  2. Create instantiable wrapper classes around all those static utilities so they can be injected into the classes that use them. This sounds like a relatively clean solution but I fear we'll end up creating an awful lot of those wrapper classes.
  3. Extract every call to these static helper classes into a function that can be overridden and test a subclass of the class I actually want to test.

But I keep thinking that this just has to be a problem that many people have to face when doing TDD - so there must already be solutions for this problem.

What is the best strategy to keep classes that use these static helpers testable?

share|improve this question

migrated from stackoverflow.com May 10 '12 at 10:49

This question came from our site for professional and enthusiast programmers.

    
I'm not sure what you mean by "credible and/or official sources" but I agree with what @berecursive has written in his answer. PowerMock exists for a reason and it shouldn't feel like "giving up" especially if you don't want to write wrapper classes yourself. Final and static methods are a pain when it comes to unit testing (and TDD). Personally? I use method 2 that you described. –  Deco May 7 '12 at 9:04
    
"credible and/or official sources" is just one of the options you can select when starting a bounty for a question. What I actually mean: Experiences from or references to articles written by TDD experts. Or any kind of experience by someone who has faced the same problem... –  Benedikt May 7 '12 at 9:30
add comment

6 Answers

This is definitely an opinionated question/answer but for what it's worth I thought I'd throw my two cents in. In terms of TDD style method 2 is definitely the approach that follows it to the letter. The argument for method 2 is that if you ever wanted to replace the implementation of one of those classes - say an ImageIO equivalent library - then you could do it whilst maintaining confidence in the classes that leverage that code.

However, like you mentioned, if you use a lot of static methods then you will end up writing a lot of wrapper code. This might not be a bad thing in the long run. In terms of maintainability there are certainly arguments for this. Personally I would prefer this approach.

Having said that, PowerMock exists for a reason. It is a fairly well known issue that testing when static methods are involved is seriously painful, hence the inception of PowerMock. I think you need to weigh up your options in terms of how much work it will be to wrap all of your helper classes vs. using PowerMock. I don't think it's 'giving up' to use PowerMock - I just feel that wrapping the classes allows you more flexibility in a large project. The more public contracts (interfaces) you can provide the cleaner the separation between intent and implementation.

share|improve this answer
1  
An additional issue which I'm not relly sure about: When implementing the wrappers would you implement all of the methods of the class that is wrapped or just the ones that are currently needed? –  Benedikt Apr 27 '12 at 12:06
3  
In following agile ideas, you should do the simplest thing that works, and avoid doing work you don't need. Therefore, you should expose only the methods you actually need. –  Assaf Stone Apr 28 '12 at 9:47
    
@AssafStone agreed –  BeRecursive Apr 28 '12 at 9:59
    
Be careful with PowerMock, all of the class manipulation it has to do to mock the methods comes with a lot of overhead. Your tests will be much slower if you use it extensively. –  bcarlso May 9 '12 at 12:42
    
Do you really have to do much wrapper writing if couple your testing/migrating with adoption of an DI/IoC library? –  dsummersl May 9 '12 at 20:36
add comment

(No "official" sources here, I'm afraid - it's not like there's a specification for how to test well. Just my opinions, which will hopefully be useful.)

When these static methods represent genuine dependencies, create wrappers. So for things like:

  • ImageIO
  • HTTP clients (or anything else network-related)
  • The file system
  • Getting the current time (my favourite example of where dependency injection helps)

... it makes sense to create an interface.

But many of the methods in Apache Commons probably shouldn't be mocked/faked. For example, take a method to join together a list of strings, adding a comma between them. There's no point in mocking these - just let the static call do its normal work. You don't want or need to replace the normal behaviour; you're not dealing with an external resource or something that's hard to work with, it's just data. The result is predictable and you'd never want it to be anything other than what it'll give you anyway.

I suspect that having removed all the static calls which really are convenience methods with predictable, "pure" outcomes (like base64 or URL encoding) rather than entry points into a whole big mess of logical dependencies (like HTTP) you'll find it's entirely practical to do the right thing with the genuine dependencies.

share|improve this answer
add comment

As a reference for all who are also dealing with this problem and come across this question I'm going to describe how we decided to tackle the problem:

We are basically following the path outlined as #2 (wrapper classes for static utilities). But we only use them when it is too complex to provide the utility with the required data to produce the desired output (i.e. when we absolutely have to mock the method).

This means we don't have to write a wrapper for a simple utility like the Apache Commons StringEscapeUtils (because the strings they need can easily provided) and we do not use mocks for static methods (if we think we might need to it's time to write a wrapper class and then mock an instance of the wrapper).

share|improve this answer
add comment

I would test these classes using Groovy. Groovy is simple to add to any Java project. With it, you can mock out the static methods quite easily. See Mocking Static Methods using Groovy for an example.

share|improve this answer
add comment

I work for a major insurance company and our source code goes up to 400MB of pure java files. We have been developing the entire application without thinking about TDD. From january this year we started with junit testing for each individual component.

The best solution in our department was to use Mock objects on some JNI methods that were system dependable (written in C) and as such you could not exactly estimate the results every time on every OS. We didn't have any other option than to use mocked classes and specific implementations of JNI methods specifically for the purpose of testing the each individual module of the application for every OS we support.

But it was really fast and it has been working quite well so far. I recommend it - http://www.easymock.org/

share|improve this answer
add comment

The objects interact with each other to accomplish a goal, when you have object hard to test because of the enviroment(an webservice endpoint, dao layer accessing the DB, controllers handling http request parameters) or you want to test your object in isolation, then you mock those objects.

the necessity of mocking statics methods is a bad smell, you have to design your application more Object Oriented, and unit testing utility static methods do not add much value to the project, the wrapper class is a good approach depending on the situation, but try to test those objects that use the static methods.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.