Alex Rivera | Logout

setUp/tearDown (@Before/@After) why we need them in JUnit?

Asked 2010-09-06T02:29:34.273
72

I believe that we are all know that setUp (@Before) will execute before any test method and tearDown(@After) will execute after test method.

Also we know that Junit will create one instance of Test per test method.

my question is that can we just move setUp method content to class Constructor and remove setUp method? is there any specific reason to keep setUp method?

Edit
Report

2 Answers

61

This (old) JUnit best practices article puts it like this:

Do not use the test-case constructor to set up a test case

Setting up a test case in the constructor is not a good idea. Consider:

public class SomeTest extends TestCase
   public SomeTest (String testName) {
      super (testName);
      // Perform test set-up
   }
}

Imagine that while performing the setup, the setup code throws an IllegalStateException. In response, JUnit would throw an AssertionFailedError, indicating that the test case could not be instantiated. Here is an example of the resulting stack trace:

junit.framework.AssertionFailedError: Cannot instantiate test case: test1   
    at junit.framework.Assert.fail(Assert.java:143)
    at junit.framework.TestSuite.runTest(TestSuite.java:178)
    at junit.framework.TestCase.runBare(TestCase.java:129)
    at junit.framework.TestResult.protect(TestResult.java:100)
    at junit.framework.TestResult.runProtected(TestResult.java:117)
    at junit.framework.TestResult.run(TestResult.java:103)
    at junit.framework.TestCase.run(TestCase.java:120)
    at junit.framework.TestSuite.run(TestSuite.java, Compiled Code)
    at junit.ui.TestRunner2.run(TestRunner.java:429)

This stack trace proves rather uninformative; it only indicates that the test case could not be instantiated. It doesn't detail the original error's location or place of origin. This lack of information makes it hard to deduce the exception's underlying cause.

Instead of setting up the data in the constructor, perform test setup by overriding setUp(). Any exception thrown within setUp() is reported correctly. Compare this stack trace with the previous example:

java.lang.Illegal
answered 2010-09-06T02:50:38.867
3

The reason you need this is that for many tests you often need to initialize state before each test so that the tests can all make assumptions about the start state they're running in.

Suppose your test class wraps, say database access. After each test you'd want to remove whatever changes your tests have made to the db - if you didn't do that, each test runs against a slightly modified database. Additionally, any given test may see a different set of changes if some subset of the previous tests have failed. For example, suppose test1 does an insert, test2 checks that you're accurately reading the table size. Day 1, test1 fails, and 0 is correct. Day 2, test1 succeeds, and 1 is correct?

BTW, junit also supports @BeforeClass if you want to do a global setup, and setup and teardowns are optional.

answered 2010-09-06T02:36:50.610

Your Answer