By default every test method defined in a TestCase runs in its own instance of the TestCase. Should multiple test methods require the same system state or data, the setUp() method can be used to centralize setting up the test without the need to explicitly call a method at the start of every test. Likewise, if after every test certain objects need to be cleaned up or assertions tested, the tearDown() method is guaranteed to run, regardless of any assertion failures or errors. Remember that a test method stops executing as soon as the first assertion fails or an error is generated. This last point is a key benefit of the tearDown() method if tests use external resources or objects that should always be freed up.
1. setUp()
The setUp() method is most often used to put the system into a known good state. For complex tests this may require hooking up multiple objects or connecting to external resources. To create code that runs before every test in a TestCase, override the setUp() method as follows:
override public function setUp():void { }
Any code, including assertions, can be placed in the setUp() method. The ability to use assertions in setUp() allows quickly canceling a test if some resource or object isn't available. Note that if the setUp() method fails an assertion or throws an error, neither the intended test method or the tearDown() method will be called. This is the only case when tearDown() isn't called.
2. tearDown()
Analogous to setUp() is the tearDown() method which is run after every test in the TestCase, regardless of failed assertions or errors. It can be thought of as the finally block in a try..finally that is wrapped around the test method call. With that said a tearDown() method is not usually needed. Remember that by default every test method runs in its own instance of the TestCase. This means that class level variables will be set to instantiation values, negating any changes a previous test method many have made. Common situations where a tearDown() method is handy include executing shared assertions that should be made after every test method or releasing resources that are external to the system, such as disconnecting a Socket. To create code that runs after every test method in a TestCase, override the tearDown() method as follows:
override public function tearDown():void { }
3. Example
The following code demonstrates how each test method when runs calls the setUp(), test code, and tearDown() methods.
package { import flexunit.framework.TestCase;
public class SetUpTearDownTest extends TestCase { private var _phase:String = "instance";
override public function setUp():void { updatePhase("setUp()"); }
override public function tearDown():void { updatePhase("tearDown()"); }
public function testOne():void { updatePhase("testOne()"); }
public function testFail():void { updatePhase("testFail()"); fail("testFail() always fails"); }
public function testError():void { updatePhase("testError()"); this["badPropertyName"] = "newValue"; }
private function updatePhase(phase:String):void { trace("Running test", methodName, "old phase", _phase, "new phase", phase); _phase = phase; } } }
Sample output from running SetUpTearDownTest is:
Running test testFail old phase instance new phase setUp() Running test testFail old phase setUp() new phase testFail() Running test testFail old phase testFail() new phase tearDown() Running test testError old phase instance new phase setUp() Running test testError old phase setUp() new phase testError() Running test testError old phase testError() new phase tearDown() Running test testOne old phase instance new phase setUp() Running test testOne old phase setUp() new phase testOne() Running test testOne old phase testOne() new phase tearDown()
Notice that each test starts with a _phase value of "instance" and that regardless of an assertion failure or error, the setUp() and tearDown() methods are executed.