2

I changed a junit test class to run with Parameterized to test two different implementations of the same interface. Here it is :

@RunWith(Parameterized.class)
public class Stack_Tests {

private Stack<String> stack;

public Stack_Tests(Stack<String> stack) {
    this.stack = stack;
}

@Parameters
public static Collection<Object[]> parameters() {
    // The two object to test
    return Arrays.asList(new Object[][] { { new LinkedStack<String>() }, { new BoundedLinkedStack<String>(MAX_SIZE) } });
}

@Test
public void test() {
    ...
}

The results are wrong since I changed to Parameterized. Half of the tests fail (the same for the two objects), all of them worked before.

It works without Parameterized like this :

public class Stack_Tests {

private Stack<String> stack;

@Before
public void setUp() throws Exception {
    stack = new LinkedStack<String>();
}

@Test
public void test() {
    ...
}

The complete test class here

dblouis
  • 568
  • 1
  • 5
  • 18

3 Answers3

3

As you suggested in the comments, try resetting the stack before every test, since previous tests change it.

You can create a new stack instance before every unit test:

@Before
public void setUp() throws Exception {
    stack = stack.getClass().newInstance();
}

Though this has the side effect that your classes must have 0-argument constructors.

Note: If some of your stacks can not have 0-argument constructors, consider invoking the constructor with arguments as per this SO answer. This means that you must provide the constructor types list and its arguments list along with the stack object to the unit test class as parameters. Then you can do:

@Before
public void setUp() throws Exception {
    stack = stack.getClass().getDeclaredConstructors(typesList).newInstance(argsList);
}
Community
  • 1
  • 1
Genti Saliu
  • 2,643
  • 4
  • 23
  • 43
  • Then all my classes must have an empty constructor, right ? – dblouis Feb 07 '16 at 16:16
  • Yes, they have to have an empty constructor. I will improve my answer in a bit, so that you can still pass in objects instead of classes to the Test class. – Genti Saliu Feb 07 '16 at 16:17
  • Note that this does undo the MAX_SIZE argument to `new BoundedLinkedStack(MAX_SIZE)` given as parameter in the question. – avandeursen Feb 07 '16 at 20:50
2

add :

@Before
public void setUp() throws Exception {
    stack.clear();
}

the stack is shared for each test, and your tests modify the stack.

avandeursen
  • 8,458
  • 3
  • 41
  • 51
Jérémie B
  • 10,611
  • 1
  • 26
  • 43
  • Well it works but it kind of ugly and impractical, it should re-instatiate every times (like with a normal test) ... What if my object if more complicated and cannot reset to its original state ? – dblouis Feb 07 '16 at 16:01
  • try Spock, it's way better than pure junit, and have a lot a helpful tools for this kind of tests ! – Jérémie B Feb 07 '16 at 16:03
  • Don't take it wrong but I don't think proposing another library to resolve a problem is really a solution ... – dblouis Feb 07 '16 at 16:05
  • i know, i didn't post this as an answer. but there is not any good answer for this : it's the way parameterized works in junit. you can write your own @Rule or JUnitRunner 'Parameterized' is you don't like the default - but it's what others libraries like spok already does. – Jérémie B Feb 07 '16 at 16:08
  • Nice. Note that this assumes all stacks given as parameter are empty. – avandeursen Feb 07 '16 at 20:46
1

To get a consistent stack for all tests, an alternative approach is to clone the stack before modifying it in a particular test.

@Test public void testPush() {
  Stack<String> myStack = (Stack<String>) stack.clone();
  myStack.push("hello");
  assertFalse(myStack.empty());
}

Thus, every test that modifies the stack should first clone it.

This is a little more cumbersome, but allows to provide more sophisticated stacks as parameters (e.g., ones with some elements to start with).

avandeursen
  • 8,458
  • 3
  • 41
  • 51