UPDATE 12/05/07: Luke Bayes has added the RemotingTestCase to AsUnits repository. Thanks Luke!

AsUnit is the first choice for Test-Driven Development using pure Flash applications. However, currently you find only one test case for asynchronous data using an instance of the flash.net.URLLoader class, but it seems neither for calling methods based on Flash Remoting using the flash.net.NetConnection class. So I decided to add a new test case called asunit.framework.RemotingTestCase” to the AsUnit Framework and hope it would be helpful for the community – check it out ;-)

Examples

Successfully asynchronous tests

Unsuccessfully asynchronous tests


Source

For more information check out the comments within the code, too ;-)

asunit.framework.RemotingTestCase ( Download code )

  1. package asunit.framework
  2. {
  3.     import flash.errors.IllegalOperationError;
  4.     import flash.events.IOErrorEvent;
  5.     import flash.events.NetStatusEvent;
  6.     import flash.events.SecurityErrorEvent;
  7.     import flash.net.NetConnection;
  8.     import flash.net.ObjectEncoding;
  9.     import flash.net.Responder;
  10.    
  11.     import asunit.framework.TestCase;
  12.     import asunit.util.ArrayIterator;   
  13.  
  14.     /**
  15.      * RemotingTestCase
  16.      * @author  Jens Krause [www.websector.de]
  17.      * @date    11/29/07
  18.      *
  19.      */
  20.     public class RemotingTestCase extends TestCase
  21.     {
  22.  
  23.         protected var connection: NetConnection;
  24.         /**
  25.         * Constructor
  26.         * @param testMethod  String      Name of the test case
  27.         *
  28.         */     
  29.         public function RemotingTestCase(testMethod: String = null)
  30.         {
  31.             super(testMethod);
  32.         }
  33.  
  34.         /**
  35.         * Inits a netConnection instance and add all necessary event listeners
  36.         *
  37.         */ 
  38.         protected function initConnection():void
  39.         {
  40.             if (connection == null)
  41.             {
  42.                 connection = new NetConnection();
  43.                
  44.                 connection.addEventListener(NetStatusEvent.NET_STATUS, connectionStatusHandler);
  45.                 connection.addEventListener(IOErrorEvent.IO_ERROR, connectionIOErrorHandler);
  46.                 connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR , connectionSecurityErrorHandler);       
  47.             }
  48.         }
  49.  
  50.         /**
  51.         * Dispose the netConnection instance
  52.         *
  53.         */         
  54.         protected function disposeConnection():void
  55.         {
  56.             if (connection != null)
  57.             {
  58.                 connection.removeEventListener(NetStatusEvent.NET_STATUS, connectionStatusHandler);
  59.                 connection.removeEventListener(IOErrorEvent.IO_ERROR, connectionIOErrorHandler);
  60.                 connection.removeEventListener(SecurityErrorEvent.SECURITY_ERROR , connectionSecurityErrorHandler)
  61.                
  62.                 connection = null;     
  63.             }
  64.         }
  65.  
  66.         /**
  67.         * Callback handler for receiving SecurityErrorEvent
  68.         * @param event    SecurityErrorEvent
  69.         *
  70.         */ 
  71.         protected function connectionSecurityErrorHandler(event: SecurityErrorEvent): void
  72.         {
  73.             result.addError(this, new IllegalOperationError(event.toString()));
  74.             isComplete = true
  75.         }
  76.  
  77.         /**
  78.         * Callback handler for receiving IOErrorEvent
  79.         * @param event    IOErrorEvent
  80.         *
  81.         */ 
  82.         protected function connectionIOErrorHandler(event: IOErrorEvent): void
  83.         {
  84.             result.addError(this, new IllegalOperationError(event.toString()));
  85.             isComplete = true;
  86.         }
  87.  
  88.         /**
  89.         * Callback handler for receiving NetStatusEvent
  90.         * @param event    NetStatusEvent
  91.         *
  92.         */
  93.         protected function connectionStatusHandler(event: NetStatusEvent): void
  94.         {
  95.            
  96.         }
  97.  
  98.         /**
  99.         * Connects the gateway
  100.         *
  101.         * @param $gateway      String  Remote gateway
  102.         * @param $encoding    uint    Object encoding using either AMF0 or AMF3
  103.         *
  104.         */                 
  105.         protected function connect ($gateway: String = null, $encoding: uint = 0): void
  106.         {
  107.             initConnection();
  108.            
  109.          connection.objectEncoding = ($encoding > ObjectEncoding.AMF0) ? $encoding : ObjectEncoding.AMF0;
  110.                
  111.          try {
  112.           connection.connect($gateway);
  113.          }
  114.          catch(error: Error)
  115.          {
  116.              result.addError(this, error);                   
  117.          }
  118.         };
  119.    
  120.         /**
  121.         * Calls a remote service method and test it
  122.         *
  123.         * @param $method        String    Remote service
  124.         * @param $responder  Responder    Responder to handle remoting calls
  125.         * @param $arguments  Array        Rest paramaters (optional)
  126.         *
  127.         */ 
  128.         protected function call ($method: String = null, $responder: Responder = null, …$arguments): void 
  129.         {
  130.             var hasReferenceError: Boolean = false;
  131.            
  132.             // parameters for calling connection.call();
  133.             // To avoid using the type unsafe …rest operator I decided to use type safe parameters within RemotingTestCase.call()
  134.             // and apply these later to connection.call();
  135.             var params: Array = [];
  136.            
  137.             // check remote method
  138.             if ($method != null)
  139.             {
  140.                 params.push($method);         
  141.             }
  142.             else
  143.             {
  144.                 result.addError(this, new ReferenceError("RemotingTestCase.call() has to defined a remote method."));         
  145.                 hasReferenceError = true;
  146.             }
  147.            
  148.             // check responder
  149.             if ($responder != null)
  150.             {
  151.                 params.push($responder);           
  152.             }
  153.             else
  154.             {
  155.                 result.addError(this, new ReferenceError("RemotingTestCase.call() has to defined a responder to handling its results."));            
  156.                 hasReferenceError = true;         
  157.             }   
  158.            
  159.             // In case of a reference error invoke test running instantly
  160.             // to show the errors created above and return
  161.             if (hasReferenceError)
  162.             {
  163.                 super.run();
  164.                 return;
  165.             }
  166.            
  167.            
  168.             var arrIterator: ArrayIterator = new ArrayIterator($arguments);
  169.             while (arrIterator.hasNext())
  170.             {
  171.                 params.push(arrIterator.next());   
  172.             }   
  173.            
  174.             // call remote service
  175.          try {
  176.                 connection.call.apply(null, params);               
  177.          }
  178.          catch(error: Error)
  179.          {
  180.              result.addError(this, error);                    
  181.          }
  182.             
  183.  
  184.         };   
  185.     }
  186. }
  187.  

The following test example based on my Flash Remoting example using OpenAMF described at the previous article called “Best practices: Custom class mapping using OpenAMF and AS3 (Flash CS3 – not Flex)”

RemotingTestCaseExample.as ( Download code )

  1. package tests
  2. {
  3.     import flash.net.ObjectEncoding;
  4.     import flash.net.Responder;
  5.    
  6.     import asunit.framework.RemotingTestCase;   
  7.  
  8.     /**
  9.      * RemotingTestCaseExample
  10.      * @author  Jens Krause [www.websector.de]
  11.      * @date    11/29/97
  12.      */
  13.     public class RemotingTestCaseExample extends RemotingTestCase
  14.     {      
  15.         private var _result: Object;
  16.         private var _userVO: UserVO;
  17.        
  18.         /**
  19.         * Constructor
  20.         * @param testMethod  String      Name of the test case
  21.         *
  22.         */ 
  23.         public function RemotingTestCaseExample(testMethod: String = null)
  24.         {
  25.             super(testMethod);
  26.            
  27.         }
  28.  
  29.         /**
  30.         * After a test is executed the tearDown method is called
  31.         * and removed all references to test objects
  32.         *
  33.         */     
  34.         override protected function tearDown():void
  35.         {         
  36.             _userVO = null;
  37.         }
  38.  
  39.         /**
  40.         * Before a test is executed the setUp method is called
  41.         * which instantiate all necessary test objects
  42.         *
  43.         */ 
  44.  
  45.          override protected function setUp(): void
  46.          {
  47.             _userVO = _result as UserVO;
  48.          }
  49.  
  50.         /**
  51.         * Runs the test
  52.         *
  53.         */     
  54.         public override function run():void
  55.         {
  56.             UserVO.register();
  57.            
  58.             _result = new Object()
  59.                    
  60.             var gateway: String = "http://localhost:8080/mappingExample/gateway";
  61.             var encoding: uint = ObjectEncoding.AMF0;
  62.            
  63.             var method: String = "de.websector.blog.openamf.mapping.services.UserServices.getUserByName";
  64.             var responder:Responder = new Responder(onResult, onFault);
  65.            
  66.             super.connect(gateway, encoding);
  67.            
  68.             super.call(method, responder, "Luke Skywalker");   
  69.  
  70.         }
  71.        
  72.         /**
  73.         * Callback handler for receiving a fault
  74.         * @param $result        Object
  75.         *
  76.         */ 
  77.         private function onFault($result: Object):void
  78.         {
  79.             result.addError(this, new Error($result.toString()));
  80.             // call super.run() to execute test methods
  81.             super.run();
  82.         }
  83.        
  84.         /**
  85.         * Callback handler for receiving a result
  86.         * @param $result        Object
  87.         *
  88.         */   
  89.         private function onResult($result: Object):void
  90.         {
  91.             _result = $result;
  92.  
  93.             super.disposeConnection();   
  94.             // call super.run() to execute test methods
  95.             super.run();
  96.         }
  97.        
  98.         /**
  99.         * Tests the userVO
  100.         */
  101.         public function testUserVO():void
  102.         {
  103.             assertTrue("result is instance of ", _result is UserVO);   
  104.         }
  105.        
  106.         /**
  107.         * Tests the userName
  108.         */
  109.         public function testUserName():void
  110.         {   
  111.             assertEquals("UserName Luke Skywalker", _userVO.userName, "Luke Skywalker");               
  112.         }   
  113.  
  114.         /**
  115.         * Tests the registerDate
  116.         */
  117.         public function testRegisterDate():void
  118.         {   
  119.             assertTrue("Register date ", _userVO.registerDate is Date)
  120.         }   
  121. //   
  122. //    /**
  123. //     * Test that is born to lose.
  124. //     */
  125. //    public function testFail():void
  126. //    {
  127. //     assertFalse("failing test", true);
  128. //    }
  129.                
  130.     }
  131. }
  132.  

Download

Source including test example files:
RemotingTestCaseExample.zip (Downloads: 707)

Happy (asynchronous) testing! ;-)

Acknowledge

3 Responses to “AsUnit (AS3): RemoteTestCase for testing asynchronous data using Flash Remoting”

  1. Luke Bayes Says:

    Hey Jens,

    I have added this class to source control with the hope of including it in the next release, please let me know if that’s OK with you.

    Thanks!

  2. sectore Says:

    Hi Luke,

    definitely – it would be great to see the RemotingTestCase in the next release of AsUnit!

    Thanks for your support ;)

    -sectore

  3. valyard Says:

    > * @date 11/29/97
    cool, this file is mad old!

    hehe, I need asynchronous tests for my animation stuff which I don’t really know how to implement

Leave a Reply

Follow sectore on Twitter