I see many Java examples using dependency injection with private fields without a public setter like this:
public SomeClass {
@Inject
private SomeResource resource;
}
But that is a bad idea when the injection should be performed manually for example in unit tests.
There are several possibilities to solve this:
- add a public setter:
setSomeResource(SomeResource r)
- make the field public
- make the field package protected
I'd like to avoid the setter, since nothing really happens in it. So I'd prefer public or package protected. What do you recommend?
I prefer the setter
But that's just my opinion
One way to avoid creating a setter for the field is using constructor injection. This even allows you to declare the field as final.
It goes like this:
I recommend using setter. In this question are the benefits of using getters and setters.
Possible solutions to this:
Use a CDI-aware testing framework like JGlue CDI-Unit. This way you need no setter. You only define the dependency inside your tests - usually using a Mockito mock object. IMHO this is the best solution, since it doesn't require you to do anything extra for testing.
Inject into Constructor or setter. That's right, you can inject into setters! More details here.
Use a protected setter. Simple and works in every case. Since it's protected, you can access it from your test class (which should have the same package definition as your tested class), and no other packages can access it.
Use a getter and override it when testing. In your test class, create a new inner class that extends the tested class and override the getter. This, however, has a big disadvantage: your test class has to use the getter internally instead of the field. Lots of potentially bugged boilerplate...
Adding setters is not an optimal solution, since you are adding production code which is not needed.
An alternative is to use Spring's ReflectionTestUtils class to inject your test dependencies using reflection, see http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/test/util/ReflectionTestUtils.html
EDIT (2017): However, reflection is an even worse solution than adding setters. The cause of this mess is the fact that Spring makes it possible to inject values without setters or constructors. My current stance is to stick to using either of those and avoid using black magic injection practices.
With the help of the answer to my (related to this one) question:
How do app servers inject into private fields?
I coded this simple example on how to inject without setters. Perhaps it helps
Run output: