Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 642
mhshams Avatar asked Sep 06 '10 02:09

mhshams


People also ask

What is setup and teardown in JUnit?

JUnit creates all the TestCase instances up front, and then for each instance, calls setup(), the test method, and tearDown(). In other words, the subtle difference is that constructors are all invoked in batch up front, whereas the setUp() method is called right before each test method.

What is the use of setup () and teardown ()?

Prepare and Tear Down State for a Test Class XCTest runs setUp() once before the test class begins. If you need to clean up temporary files or capture any data that you want to analyze after the test class is complete, use the tearDown class method on XCTestCase .

What is teardown method in JUnit?

tearDown() methodThe JUnit framework makes sure that after each test case is run, the method under @After is surely executed. The objects used up in the test have to be set NULL in the teardown() method so that the garbage from the tests gets collected.

What does the teardown () function do?

teardown: Run code on setup/teardown Code in a teardown() block is run upon completion of a test file, even if it exits with an error. Multiple calls to teardown() will be executed in the order they were created.


2 Answers

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.IllegalStateException: Oops     at bp.DTC.setUp(DTC.java:34)      at junit.framework.TestCase.runBare(TestCase.java:127)     at junit.framework.TestResult.protect(TestResult.java:100)     at junit.framework.TestResult.runProtected(TestResult.java:117)     at junit.framework.TestResult.run(TestResult.java:103)     ... 

This stack trace is much more informative; it shows which exception was thrown (IllegalStateException) and from where. That makes it far easier to explain the test setup's failure.

like image 177
Pascal Thivent Avatar answered Sep 20 '22 21:09

Pascal Thivent


At work we've discovered something rather interesting which answers your question. When you run a test suite, especially a large set of tests (200+) JUnit starts to use a LOT of memory, this is because ALL the tests are instanced before any actual test method is run.

We ran into a "memory leak" because of this because we used Spring to wire in some JPA EntiryManager objects for our database tests, this became A LOT of objects and a lot of memory and about half way through the tests we were getting OutOfMemory exceptions.

IMHO, best practise is to use setUp and tearDown to inject your dependencies and null out any and all class references, this will make your tests run faster and save you a lot of head ache!

Hope you learn from our mistakes :)

like image 28
BjornS Avatar answered Sep 16 '22 21:09

BjornS