I was annoyed to find in the Parameterized documentation that "when running a parameterized test class, instances are created for the cross-product of the test methods and the test data elements." This means that the constructor is run once for every single test, instead of before running all of the tests. I have an expensive operation (1-5 seconds) that I put in the constructor, and now the operation is repeated way too many times, slowing the whole test suite needlessly. The operation is only needed once to set the state for all of the tests. How can I run several tests with one instance of a parameterized test?
Asked
Active
Viewed 3,633 times
9
-
tests should be run in isolation. if you can, follow Duncan Jones' suggestion. – Ray Tayek Jan 21 '13 at 16:31
1 Answers
8
I would move the expensive operation to a @BeforeClass
method, which should execute just once for the entire parameterized test.
A silly example is shown below:
@RunWith(Parameterized.class)
public class QuickTest {
private static Object expensiveObject;
private final int value;
@BeforeClass
public static void before() {
System.out.println("Before class!");
expensiveObject = new String("Just joking!");
}
@Parameters
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][] { { 1 }, { 2 } });
}
public QuickTest(int value) {
this.value = value;
}
@Test
public void test() {
System.out.println(String.format("Ran test #%d.", value));
System.out.println(expensiveObject);
}
}
Will print:
Before class!
Ran test #1.
Just joking!
Ran test #2.
Just joking!

Duncan Jones
- 67,400
- 29
- 193
- 254
-
Ah! Thanks. I was using Before and AfterClass as if they would run before and after the first and last parameterized tests. Is there a way to do that (static block for before, and something else for after...)? – Nate Glenn Jan 21 '13 at 18:54
-
Not sure I understand what you want. `@BeforeClass` and `@AfterClass` would allow you to set-up and tear-down your test data. Both need to be `public static void` methods. – Duncan Jones Jan 21 '13 at 19:03
-
Yes, that's exactly what I asked for in my question. I was just wondering, because I was using BeforeClass and AfterClass incorrectly, if there's a way to run stuff before starting any of the tests and after finishing all of the tests. – Nate Glenn Jan 21 '13 at 19:05
-
I'm very confused now! To run stuff before starting any tests, use `@BeforeClass`. To run stuff after all the tests, use `@AfterClass`. There are no other options that I know of! What functionality are you looking for that isn't provided by `@BeforeClass` and `@AfterClass`? – Duncan Jones Jan 21 '13 at 19:11
-
`@BeforeClass` and `@AfterClass` are run before and after each parameterized test. So, with 5 parameter elements they would each run 5 times. I'm asking for something that would be run by JUnit before and after running all of the parameterized tests. So even with 5 parameter elements they would only be run once. – Nate Glenn Jan 21 '13 at 20:56
-
Well, since what I was asking for before wasn't really an option, here's another question: can I access the parameters from the @BeforeClass method? – Nate Glenn Jan 22 '13 at 04:13
-
Apologies for the lengthy confusion here. However, I think you and I are seeing fundamentally different results when using `@BeforeClass`. I observe that this method is only run *once* per parameterized test class, regardless of how many test methods there are. – Duncan Jones Jan 22 '13 at 07:45
-
let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/23133/discussion-between-duncan-jones-and-nate-glenn) – Duncan Jones Jan 22 '13 at 07:45