Home > Development > Shoud you change your design for testing purposes?

Shoud you change your design for testing purposes?

As Dependency Injection frameworks go, the standard is currently CDI. When switching from Spring, one has to consider the following problem: how do you unit test your injected classes?

In Spring, DI is achieved through either constructor injection or setter injection. Both allow for simple unit testing by providing the dependencies and calling either the constructor or the desired setter. Now, how do you unit test the following code, which uses field injection:

public class MyMainClass {

  @Inject
  private MyDependencyClass dependency;

  // dependency is used somewhere else
  ...
}

Of course, there are some available options:

  1. you can provide a setter for the dependency field, just as you did in Spring
  2. you can use reflection to access the field
  3. you can use a testing framework that does the reflection for you (PrivateAccessor from JUnit addons or Powermock come to mind)
  4. you can increase the field visibility to package (i.e. default) and put the test case in the same package

Amazingly enough, when Googling through the web, the vast majority of unit testing field-injected classes code demonstrate the increased visibility. Do a check if you do not believe me: they do not display the private visibility (here, here and here for example). Granted, it’s a rather rethorical question, but what annoys me is that it’s implicit, whereas IMHO it should be a deeply thought-out decision.

My point is, changing design for testing purpose is like shooting yourself in the foot. Design shouldn’t be cheaply sold. Else, what will be the next step, changing your design for build purposes? Feels like a broken window to me. As long as it’s possible, I would rather stick to using the testing framework that enable private field-access. It achieves exactly the same purpose but at least it keeps my initial design.

email
Send to Kindle
Categories: Development Tags:
  1. Roger Parkinson
    January 23rd, 2012 at 09:08 | #1

    For setting mocks I agree with you. I still use Spring and I use a different beans xml file to inject test mocks. Test code is in the same package. Sometimes I change a method from private to protected so that test code can call it directly for testing. In that case I’m changing the design. So I can see I should start using PrivateAccessor. I never do that to a setter, though.

    But I do want to make the point that testability is part of the design. Before I used DI I had horrible designs from a testing point of view and a lot of my better design work came out of asking the question: How can I make this easier to test?

  2. February 5th, 2012 at 23:49 | #2

    “If you have to change your design for testing, it means you’re lacking some concepts ;)”

    Actually, apart from the quick “quote” above, I almost only have to revert to package private fields/methods for code which wasn’t written in a TDD way. At least I’ve this feeling. Do you share it?

  1. No trackbacks yet.