b-log – betriebsraum weblog

Software Development, Human-Computer Interaction, Projects…

Asynchronous Callback Functions in FlexUnit

July 20, 2010

FlexUnit provides support for asynchronous testing with the Async class. While this class works well for event driven tests, it doesn’t support callback functions like you might want it to. A typical event driven asynchronous test looks like this:

[Test(async, description="Async Example")]
public function testFancyInstanceFiresComplete():void {
    var asyncHandler:Function = Async.asyncHandler(this, doStuffComplete, 500);
    fancyInstance.addEventListener(FancyEvent.COMPLETE, asyncHandler, false, 0, true);
    fancyInstance.doStuff();			
}

If you need to test a method using a callback function you *could* write:

[Test(async, description="Async Callback Example")]
public function testFancyInstanceFiresComplete():void {
    var asyncHandler:Function = Async.asyncHandler(this, doStuffComplete, 500);
    fancyInstance.doStuff(asyncHandler);			
}

However, this can cause runtime errors when some callback parameter type cannot be converted to the expected event object. One possible solution is to use a utility class to generate the callbacks:

package de.betriebsraum.utils.tests {
 
    import flash.events.Event;
    import flash.events.EventDispatcher;
 
    import org.flexunit.async.Async;
 
    public class AsyncUtil extends EventDispatcher {
 
        public static const ASYNC_EVENT:String = "asyncEvent";
 
        private var _testCase:Object;
        private var _callback:Function;
        private var _passThroughArgs:Array;
        private var _callbackArgs:Array;
 
        public function AsyncUtil(testCase:Object, callback:Function, passThroughArgs:Array = null) {
            _testCase = testCase;
            _callback = callback;
            _passThroughArgs = passThroughArgs;
        }
 
        public static function asyncHandler(testCase:Object, callback:Function, passThroughArgs:Array = null, timeout:Number = 1500):Function {
            var asyncUtil:AsyncUtil = new AsyncUtil(testCase, callback, passThroughArgs);
            asyncUtil.addEventListener(ASYNC_EVENT, Async.asyncHandler(testCase, asyncUtil.asyncEventHandler, timeout));
            return asyncUtil.asyncCallbackHandler;
        }
 
        public function asyncEventHandler(ev:Event, flexUnitPassThroughArgs:Object = null):void {
            if (_passThroughArgs) {
                _callbackArgs = _callbackArgs.concat(_passThroughArgs);
            }
            _callback.apply(null, _callbackArgs);
        }
 
        public function asyncCallbackHandler(...args:Array):void {
            _callbackArgs = args;
            dispatchEvent(new Event(ASYNC_EVENT));            
        }
 
    }
 
}

Using this class you can safely add callback functions without getting any runtime errors:

[Test(async, description="Async Callback Example")]
public function testFancyInstanceFiresComplete():void {
    var asyncHandler:Function = AsyncUtil.asyncHandler(this, doStuffComplete);
    fancyInstance.doStuff(asyncHandler);			
}

Hope it helps…

Filed under: Flex/AS3, Software Development

Add a comment

You must be logged in to post a comment.