AsUnit (AS3): RemoteTestCase for testing asynchronous data using Flash Remoting
Posted on November 29, 2007
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 ;-)
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 }
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)"
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 // }
Download
Source including test example files: RemotingTestCaseExample.zip
Happy (asynchronous) testing! ;-)
Acknowledge
- [AS3] Jonathan Marston: asunit testing with flash cs3 and actionscript 3
- [AS2] Tim Beynart - FlashCodersNY: ASUnit Step-By-Step: Part One
- [AS2] Tim Beynart - FlashCodersNY: Unit testing for ActionScript 2.0, Part 2
UPDATE (12/05/07)
Luke Bayes has added the RemotingTestCase
to AsUnits repository. Thanks Luke!