July 24, 2004Configuration injection in testsWhy does JUnit force you to have test() and setUp() methods that don't have any parameters? Because there is no easy way in Java 1.4 and under to specify the values for these parameters. As a consequence to this shortcoming, various JUnit add-ons have added the possibility to look up property files in your setUp() method which are then initialized inside your test method (and incidentally, will be initialized over and over again for each invocation of the test method, as I reported in an earlier JUnit bug report). A better way to address this problem is to use annotations as a bridge between your Java code and a property file. I just added support for this in TestNG, and here is how it works (excerpt from the new TestNG documentation). ParametersTest methods don't have to be parameterless. You can use an arbitrary number of parameters on each of your test method, and you instruct TestNG to pass you the correct parameters with the parameters method on the @Test annotation. For example:
@Test(parameters = { "first-name" })
public void testSingleString(String firstName) {
System.out.println("Invoked testString " + firstName);
assert "Cedric".equals(firstName);
}
In this code, we specify that the Java parameter "firstName" of your Java method
should receive the value of the property called first-name. This
property is defined in the testng.properties that you used to invoke this test:
#testng.properties first-name = Cedric The same technique can be used for the @Configuration annotations:
@Configuration(beforeTestMethod = true,
parameters = {"datasource", "jdbc-driver")
public void beforeTest(String ds, String jdbcDriver) {
m_dataSource = ...; // look up the value of datasource
}
This time, the two Java parameter ds
and driver will receive the value given to the properties datasource
and jdbc-driver respectively. Note that the properties are mapped to the
Java parameters in the same order as they are found in the annotation, and TestNG will
issue an error if the numbers don't match.
This system allows for a flexible configuration of the runtime configuration of your tests and allow you to arbitrarily define how granular this configuration will be (configuration method or test method). Comments
Yuck! Now someone has to look in multiple files to understand what your test does. The fact that JUnit setUp and test functions take no parameters is a GOOD thing. It forces the programmer to explicitly define a unit's dependencies, which makes it easier for somebody else to understand the test, and thereby understand the class under test. It also makes it hard to test a unit that requires a lot of dependencies and external configuration, which gives valuable feedback about the quality of the design of the class under test. Posted by: at July 23, 2004 01:50 AMIt would certainly be useful to have parameterized test methods, but passing string properties to the test is not really it as there is no real benefit over acquiring the values at the beginning of the test. public void testSomeDBStuff(DataSource ds) { and the framework supplies the datasource from somewhere. The point here is that to understand the test it is not important how and where the datasource is acquired, but only what the test does with it. And IMO there is no need for annotations here, plain IoC usage or similar would probably suffice. Posted by: Thomas Dudziak at July 23, 2004 03:35 AMwhy not just use a variable-length argument list? Posted by: Jonathan Ellis at July 23, 2004 05:50 AMExactly my thought (Jonathan's). Posted by: Sumit at July 23, 2004 10:52 AMPost a comment
|