Saturday, February 6, 2010

JUnit

The setup() and tearDown() methods of the TestCase class apparently behaves differently from what some people would have thought. If these methods are used in a test class, one would think that it would be only called once for the lifetime of the test class. But it is not the case.

To illustrate this further, lets consider the sample code below. It's main purpose is to show how the methods above behaves when the test case is run.

Say we have this test class:

1.public class TestPerson extends TestCase{
2.       private Person person;
3.
4.       protected void setup(){//create Greg
5.           person = new Person("Greg");
6.       }
7.
8.       protected void tearDown(){
9.           person = null;
10.      }
11.
12.       public void testCreateChild(){
13.          person.createChild("Nimfa");
14.       }
15.
16       public void testMarrySomebody(){
17.           person.getMarriedTo("Laila");
18.       }
19.}

When this test case is run, here's what's going to happen:

1. At line 2, the person variable is declared and initialized
2. At line 4, setup() method is called
3. At line 12,  testCreateChild() method is called (assuming this is the first method called)
4. At line 8,  tearDown() method is called
5. At line 2, the person variable is declared and initialized again
6. At line 4, setup() method is called is called again
7. At line 16,  testMarrySomebody() is called
8. At line 8,  tearDown() method is called

After code execution, Greg will loose a child names Nimfa then get married to Laila instead of having both the child and getting married. Sad story....

Here's the explanation. In a nutshell, the number of test methods we have, in this case two(testCreateChild() and testMarrySomebody()), is directly proportional to the calls of the setup() and tearDown() methods and to the declaration and initialization of the member attributes. The variable person will be instantiated again with a new Person object but with the same value which is 'Greg' for each method loosing the previous state of the child created. Greg will always end up getting married and not having a child.

If the intention on line 5 is to create an object which has a state consistent across all test methods, then it is a problem, since JUnit will basically create a new object per test methods. Object state maybe different from each test methods. The best approach would be to not use the setup() but instead initialize the object in the test method itself. So the object(s) initialized at the setup() method is never reused to the rest of the test methods. The tearDown() method is not necessary since it's just destroying the created object unless, a specific resource(i.e. database connection, etc.) needs to be released and should be called here.

No comments:

Post a Comment