Take heed of mixing JUnit 4’s Parameterized tests
One of the most handy features of JUnit 4 is its ability to run parameterized tests, which essentially means you can create a generic test and run it multiple times with various test parameters. In previous versions of JUnit, if you wanted to simulate this same behavior, you’d have to either:
- loop over a collection of values
- which means if there was a failure, the loop wouldn’t terminate
- write unique test cases for each test data combination
- which could prove to be a lot of coding
With parameterized tests, you can create a highly flexible testing scenario in five easy steps:
- Create a generic test and decorate it with the @Test annotation
- Create a static feeder method that returns a Collection type and decorate it with the @Parameters annotation
- Create class members for the parameter types required in the generic method defined in Step 1
- Create a constructor that takes these parameter types and correspondingly links them to the class members defined in Step 3
- Specify the test case be run with the Parameterized class via the @RunWith annotation
For example, the following test defines a generic test dubbed verifyGoodZipCode that tests four different combinations of zip codes defined in the feeder method named regExValues. Note too, the use of the @Parameters annotation and the @RunWith(Parameterized.class) class level decoration.
@RunWith(Parameterized.class)
public class ParametricRegularExpressionTest {
private String phrase;
private boolean match;
private static String zipRegEx = "^\d{5}([\-]\d{4})?$";
private static Pattern pattern;
public ParametricRegularExpressionTest(String phrase, boolean match) {
super();
this.phrase = phrase;
this.match = match;
}
@Parameters
public static Collection regExValues() {
return Arrays.asList(new Object[][] {
{"22101", true },
{"221x1", false },
{"22101-5150", true },
{"221015150", false }});
}
@Test
public void verifyGoodZipCode() throws Exception{
Matcher mtcher = this.pattern.matcher(phrase);
boolean isValid = mtcher.matches();
assertEquals("Pattern did not validate zip code", isValid, match);
}
@BeforeClass
public static void setUpBeforeClass() throws Exception {
pattern = Pattern.compile(zipRegEx);
}
}
The astute reader will notice a subtle pattern relating to parameterized classes in JUnit 4– because of the member variable mapping with constructors, it becomes obvious that JUnit creates a new instance of the enclosing class for each test run. So in the example above, four instances will be created and the test method will be run four times with unique values relating to the Collection defined in the feeder method.
What this essentially means is that if you put a non-parametric test case in a parameterized class, it will also be run as many times as JUnit creates a new instance of your parameterized class. This isn’t a terrible thing, but it isn’t exactly elegant either. Hence, if you create parameterized test classes with JUnit 4, it probably makes sense to keep non-parameterized tests out of them. Simply put those methods in another test class.
Oh yeah, by the way, TestNG’s parameterized test classes don’t display this behavior. A non-parameterized test in a parameterized class will only be executed once. Nevertheless, JUnit 4’s parameterized test classes are an excellent way to achieve a high degree of code confidence with fewer test methods.

April 15th, 2007 at 12:59 am
Compare this to TestNG’s version:
@DataProvider
public Object[][] data() {
return new Object[][] {
{”22101″, true },
{”221×1″, false },
{”22101-5150″, true },
{”221015150″, false }});
}
@Test(dataProvider = “data”)
public void verifyGoodZipCode(String phrase, boolean match) throws Exception
{
Matcher mtcher = this.pattern.matcher(phrase);
boolean isValid = mtcher.matches();
assertEquals(”Pattern did not validate zip code”, isValid, match);
}
Much simpler and easier to read, in my opinion.
April 16th, 2007 at 1:07 pm
[…] Test Early points out a nice feature of JUnit 4 that I had overlooked — parameterized tests. If you’ve ever found yourself writing multiple repetitive test methods just so you could call the same method with various combinations of arguments, you should check it out. […]
June 20th, 2008 at 1:26 am
For those that had trouble getting Spring 2.5 to work with Junit 4.4 Paramatized tests please take a look at the example class here:
http://fisheye1.atlassian.com/browse/~raw,r=1.9/springframework/spring/tiger/test/org/springframework/test/context/junit4/ParameterizedDependencyInjectionTests.java
This method of injection worked for me.
August 15th, 2008 at 6:03 am
Thanks. Your example makes far more sense than the one in the javadoc of Parameterized.