Tuesday, April 5, 2011

Little Spring Gem: ReflectionTestUtils

I have recently been slacking on content on my blog, between long stressful hours at work and to the wonderful toy that is an iPhone, I have taken a little break from anything "development" related after leaving the office to maintain my sanity. Now with the project delivered, and things quieting down again I can re-focus my excess neuron energy back to processing more IT related information.

One little thing I discovered in my last project, which I am a little embarrassed about, being a Spring nut, is the little gem that is : ReflectionTestUtils.

I mostly try write unit tests that do not include Spring, for the reason, that you should be testing your code and not Spring config. However sometimes it's really useful and quite beneficial to have your test code wired up with Spring, be that for integration tests or just to extend your test suite.
One issue was, I always found myself adding "setters" to my component interfaces, I always hated doing it, but I would con myself by saying: "It was for more testing, and more testing is always a good thing", and move along. I eventually (while procrastinating on work I didn't really want to do) went searching for a cleaner solution.

1 search and 1 minute later, a little red faced, I kicked myself. I should have guessed straight away that Spring would have thought of this scenario From 2.5 Spring had the ReflectionTestUtils class, which simply lets you set your dependencies / mocks via reflection.

So easy, tell it which object, the name of the field and set the mock / value you want to set. Neater interfaces, good times.
Below is an example using EasyMock interfaces and inject them for my test.

4 comments:

  1. Hi Brian,

    It is kind of funny, because I spent some time in my last project with removing ReflectionTestUtils calls from our code :-)

    I believe that reflection makes the code hard to read, and when it comes to refactoring (even for test code) it is a nightmare.

    Additionally, I observed an interesting thing. After the ReflectionTestUtils appeared in the test cases, people started to use it, because it was easier, than taking care of dependency injection. So their first thought was to use the ReflectionTestUtils and not thinking about a way to inject classes properly.

    I'm not saying that ReflectionTestUtils is "evil", but watch out where and how are you using it.

    Cheers,
    Zsolt

    ReplyDelete
  2. Hi, Thanks for the comment.

    I agree, I am generally not a fan of reflection either and I always try avoid using it in code.

    I believe in this case it is handy, but as you mention unfortunately programmers often misuse things. I have seen people do unbelievably obscure things with many of the Spring features. Thankfully in my current environment most of those are picked up in code / peer reviews.

    Also in our case, using Maven and limiting the spring-test maven artifact to "test" scope should keep it out of general code.

    But...
    We all know us programmers are overly resourceful and reasonably lazy, so I'll heed your warning and will keep an eye out for it sneaking into where it doesn't belong.

    ReplyDelete
  3. ReflectionTestUtils is a gem in disguise. It can be very useful in our test code, no doubts. I too hate adding setters just because we need to set a mock object to an autowired member. But having said that, I learnt in Server side Java symposium (http://javasymposium.techtarget.com/html/agile.html#LKoskelaTestCode) that our test code should ideally be as good as production code.

    If we are mocking some members of class under test, and using the rest as autowired by Spring, why not mock'em all? Let's not be lazy. This approach will cause in longer tests(as per my experience), but these tests are much cleaner, and readable.

    ReplyDelete
  4. Why not add a test-only constructor that is package-protected and passes only fields you require in your tests?

    ReplyDelete

Popular Posts

Followers