I came across this old
entry from Ara about dependency injection in tests
.

The idea is to define your beans in XML with a framework like Spring and then
use his decorator to inject the beans inside your tests.  The problem with
this approach can be summed up in three words:  "too much magic".

Ara’s solution uses reflection to enumerate the fields in your test class and
match them against the name of the bean as declared in your XML file. 
Another problem with this approach is that you need to declare this field inside
your class whereas only a few methods might need it, but I agree that JUnit
doesn’t leave you much choice there.

I believe a better solution is simply to pass the resolved bean as a
parameter to the test method.

Ara’s test case can then simply be rewritten like this:

public void testSomething(UserDAO userDao) throws Exception {
  userDao.createAdmin();
}

The advantages of this approach are:

  • No more reflection magic and mysterious naming.
  • userDao is scoped to the method that uses it, which makes for better
    isolation.
  • Uses the standard Java way to pass parameters.
  • No need to declare it as a field.

Now, how do we get the testing framework to pass this parameter to the
method?

It’s pretty easy to do with TestNG, but as of today, passing parameters is
limited to primitive types (no XML bean support such as in Spring), so TestNG
only solves half of this problem.

In the future, I am definitely considering adding support for Spring’s bean
factory so that the limitation to primitive types can be entirely lifted. 
Then we could have:

@Test(parameters = { "user-dao" })
public void testSomething(UserDAO userDao) throws Exception {
  userDao.createAdmin();
}

and in testng.xml:

<parameter name="user-dao" spring-bean-name="user-dao-bean">

The good thing about this approach is that it leverages a well-known and
robust framework, but we now have two indirections (one Java file and two XML
file), so another possibility would be to offer bean support in testng.xml itself:

<bean name="user-dao-bean">
    <property name="userName" value="Cedric" />
</bean>
<parameter name="user-dao" bean-name="user-dao-bean">

Whatever solution we eventually support, I think that passing parameters to
test methods is a very important feature that has been overlooked for too long.