-
Notifications
You must be signed in to change notification settings - Fork 11
WrappingParameterizedRunner
NOTE: This documentation assumes you know the basics of the Parameterized runner.
The main purpose of this JUnit runner is to support the scenario where you want to combine the functionality of @RunWith(Parameterized.class)
with @RunWith(SomethingElse)
- a scenario neither supported by JUnit nor by the Parameterized runner. WrappingParameterizedRunner overcomes this through a chaining annotation which lets one specify a second runner to run the parameterized tests with.
The WrappingParameterizedRunner runner also works as a direct replacement for the Parameterized runner in cases when no other runner is needed, providing an alternative syntax (compared to Parameterized) to specify tests.
The runner is activated by annotating the test class with @RunWith(WrappingParameterizedRunner.class)
.
The runner requires the test class to contain a method which is called to determine which parameter sets the tests are to be run with. Just like with the standard Parameterized builder, the parameters are then passed to the constructor of the test class when the tests are to be run.
The test class can have multiple constructors; the parameter types are used to determine which constructor to use in each case. This resolution is done immediately when the parameters are given to the runner; thus failure to give correct parameters are detected while the parameters are generated and it's easy to find how the broken parameters came to be. This resolution is done even when only a single constructor exists to get the same benefits.
The method for creating parameter sets must be declared in the test class as such:
@ParameterizedSuite
public static void suite(ParameterizedSuiteBuilder builder) {
...
}
The name of the method does not matter. Inside the method the provided builder instance is used to register the parameters for constructing the test class. Example:
builder.constructWith("hello", 42);
This call will thus throw an exception if it cannot find a constructor in the test class that accepts the given arguments. Example acceptable constructor:
public MyTestClass(String input, int itemNo) {
this.input = input;
this.itemNo = itemNo;
}
If you want to parameterize the MockitoJUnitRunner runner, you add the following annotation to the test class:
@WrappedRunWith(MockitoJUnitRunner.class)
When the annotation is not present, the default JUnit4 runner is used.
WrappingParameterizedRunner is expected to be compatible with:
- all runners that
- don't apply any custom classloading of the test class
- instantiate the test class using the default constructor
- powermock (1.5.5 and newer) which does indeed apply custom classloading (explicit support included)
This means:
- WrappingParameterizedRunner can be used with
@WrappedRunWith
:- default runner (normally used when no
@RunWith
or@WrappedRunWith
annotation present) - spring (
SpringJUnit4ClassRunner
) - mockito runner
- powermock runner
- default runner (normally used when no
- can not:
-
Suite
runner -
Enclosed
runner (you can useNestedRunner
instead - also provided in this project) -
Categories
runner
-
Note however that WrappingParameterizedRunner
can be used inside a class run with the Enclosed
runner, or run by another class run with the Suite runner. The above limitations refer to whether they can be used with the @WrappedRunWith
annotation or not.
If you find a runner WrappingParameterizedRunner
does not work with, file a bug!
Example that wraps the MockitoJUnitRunner
and sets up 3 sets of parameters, one of which has a custom name (shown in the JUnit test tree in Eclipse for example). The default name contains the parameter set index and the parameter values.
@RunWith(WrappingParameterizedRunner.class)
@WrappedRunWith(MockitoJUnitRunner.class)
public class ExampleTest {
private final String str;
private final int id;
@Mock
private Runnable mock;
@ParameterizedSuite
public static void suite(ParameterizedSuiteBuilder builder) {
builder.constructWith("kala", 1);
builder.constructWith("foo", 42);
builder.constructWith("foo", 43).named("test with secret parameters");
}
public WrappingParameterizedRunnerTest(String str, int id) {
this.str = str;
this.id = id;
}
@Test
public void ensureStringNotNull() throws Exception {
assertNotNull(str);
}
@Test
public void ensureMockAvailable() throws Exception {
assertNotNull(mock);
}
@Test
@Ignore
public void ensureIdAtleast15() throws Exception {
assertTrue("Id should be at least 15, but was " + id, id >= 15);
}
}
Another example, this time not wrapping any other runner. Demonstrates that multiple constructors can be used. Tests all combinations of the numbers 0..49 and the strings "foo" and "bar", and additionally with just string "kala".
@RunWith(WrappingParameterizedRunner.class)
public class ExampleTest {
private final int i;
private final String x;
@ParameterizedSuite
public static void suite(ParameterizedSuiteBuilder builder) {
for (int i=0; i<50; ++i) {
for(String x : new String[] { "foo", "bar" }) {
builder.constructWith(i, x);
}
}
builder.constructWith("kala");
}
public WrappingParameterizedRunnerTest(int i, String x) {
this.i = i;
this.x = x;
}
public WrappingParameterizedRunnerTest(String x) {
this.i = 42;
this.x = x;
}
@Test
public void testSomeNonsense() throws Exception {
asserEquals("123", x + i);
}
}