Assume a class Foo, with a dependency Bar which is injected by some DI-Framework (CDI in this case):
public class Foo {
@Inject
private Bar bar;
...
public void someLogic() {
...
}
}
Let – for the sake of the example – Bar be a mockable infrastructural dependency, like an EntityManager or a UserTransaction, which is out of the scope of the unit test, but – again for the sake of the example – be required for Foo to be initialized properly.
Assume a unit test FooTest (I explicitly want to write unit tests without container dependencies), that needs to set or mock the dependency somehow, but otherwise tries to keep a low profile in terms of required container functionality (hence not an integration test).
public class FooTest {
private Foo foo;
@BeforeClass
public void initFoo() {
... set bar somehow ...
}
@Test
public doSomeTestOnSomeMethod() {
...
}
}
I’m trying to collect some facts of what’s the best strategy in order to set these otherwise container-controlled dependencies from within my test:
(1) Add getBar() and setBar() to Foo
(-) unnecessary, bloated code(?)
(+) straightforward
(+) works in and for all (test-)classes
(2) Use reflection to set bar
(-) complicated, harder to read & maintain
(+) works in and for all (test-)classes
(3) Remove private qualifier to make those fields accessible from within the test (assuming same package)
(+) Easiest and shortest solution
(-) Not the smallest scope in terms of production code
(-) Not usable outside of the package
Is there any clear advice on this topic?
Update: I’m aware that I can use the container as a dependency provider for tests – I do this for integration tests, but I certainly don’t want the full Java EE stack in a unit test.
I hope this does not lead to a flamewar on frameworks 😉
Update2: Thanks everyone for answering so far, but I seem to have expressed myself unclear. The answers tend to indicate that I don’t make enough use of the possibilities of the underlaying DI-framework, or simply need more mocking. That’s certainly all good and true, but I rather wanted to collect opinions on whether it’s okay to extend a class member’s visibility to default level in order to leverage testibility, if the “test-exclusive”-getter-setter approach is better, or if reflection (my current solution) is the way to go. Tried to edit the question so that it better describes my problem.
Resume and closing If I had the appropriate rights I would very much like to close this question, because I obviously expressed myself in a very misleading and somehow confusing way. I was neither looking for a discussion about correct dependency injection in tests, nor did I want any code snippets. My – gloriously failed – intention was to start a discussion on what I already wrote in Update 2. Thanks to everyone who contributed – I will certainly put more effort in future questions.
Add a setter to the class being tested and in the unit test, inject a mock version of the
Barclass. Mockito, EasyMock, JMock all make this dead simple.Without a setter on the
Fooclass, how can anyone use it outside of your container anyway? Labeling a setter as “bloat” sounds overblown to me. I believe you are overthinking the situation.An update for your update:
My personal opinion is that adding a setter is just a few additional keystrokes (which most IDEs will automate for you), whereas changing the visibility of the fields can lead to other poor choices down the road (suddenly someone decides they can write production code that uses the field directly as well, since you didn’t make it
private), and using reflection requires more code (and is slower) than simply using the setter. AsetBar(Bar)method is about as simple as it gets.