Flex 4.5.1 で記述しているクラスの単体テストを、テストとモック フレームワークにそれぞれ FlexUnit 4 とMockolateを使用して記述しようとしています。カスタム イベントにas3-signalsを使用しています。
私が書いてテストしている機能は、 ArcGIS API for Flex内のQueryTaskクラスのラッパー クラス (QueryQueue)です。これにより、実行のために複数のクエリ タスクを簡単にキューに入れることができます。私のラッパーである QueryQueue は、すべてのクエリ応答が処理されたときにイベントを送出します。completed
インターフェイスは非常にシンプルです。
public interface IQueryQueue
{
function get inProgress():Boolean;
function get count():int;
function get completed():ISignal;
function get canceled():ISignal;
function add(query:Query, url:String, token:Object = null):void;
function cancel():void;
function execute():void;
}
使用例を次に示します。
public function exampleUsage():void
{
var queryQueue:IQueryQueue = new QueryQueue(new QueryTaskFactory());
queryQueue.completed.add(onCompleted);
queryQueue.canceled.add(onCanceled);
var query1:Query = new Query();
var query2:Query = new Query();
// set query parameters
queryQueue.add(query1, url1);
queryQueue.add(query2, url2);
queryQueue.execute();
}
public function onCompleted(sender:Object, event:QueryQueueCompletedEventArgs)
{
// do stuff with the the processed results
}
public function onCanceled(sender:Object, event:QueryQueueCanceledEventArgs)
{
// handle the canceled event
}
私のテストでは、現在 QueryTaskFactory および QueryTask オブジェクトをモックしています。クエリがキューに比較的簡単に追加されることを確認するなどの簡単なテスト。
[Test(Description="Tests adding valid QueryTasks to the QueryQueue.")]
public function addsQuerys():void
{
var queryTaskFactory:QueryTaskFactory = nice(QueryTaskFactory);
var queryQueue:IQueryQueue = new QueryQueue(queryTaskFactory);
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(0));
var query1:Query = new Query();
queryQueue.add(query1, "http://gisinc.com");
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(1));
var query2:Query = new Query();
queryQueue.add(query2, "http://gisinc.com");
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(2));
var query3:Query = new Query();
queryQueue.add(query3, "http://gisinc.com");
assertThat(queryQueue.inProgress, isFalse());
assertThat(queryQueue.count, equalTo(3));
}
execute
ただし、メソッドもテストできるようにしたいと考えています。このメソッドは、キューに追加されたすべてのクエリを実行する必要があります。すべてのクエリ結果が処理されると、completed
イベントが送出されます。テストでは、次のことを確認する必要があります。
execute
各クエリで一度だけ呼び出されますinProgress = true
結果が処理されていない間inProgress = false
結果が処理されたときcompleted
結果が処理されたときにディスパッチされますcanceled
呼び出されることはありません (有効なクエリの場合)- キュー内で行われる処理は、クエリ結果を正しく処理してパッケージ化します
これまでのところ、主に weltraumpirat から提供された回答のおかげで、項目 1 から 5 のテストを作成できます。現在、実行テストは次のようになっています。
[Test(async, description="Tests that all queryies in the queue are executed and the completed signal is fired")]
public function executesAllQueriesInQueue():void
{
// Setup test objects and mocks
var query:Query = new Query();
var mockedQueryTask:QueryTask = nice(QueryTask);
var mockedQueryTaskFactory:QueryTaskFactory = nice(QueryTaskFactory);
// Setup expectations
expect(mockedQueryTaskFactory.createQueryTask("http://test.com")).returns(mockedQueryTask);
expect(mockedQueryTask.execute(query, null)).once();
// Setup handlers for expected and not expected signals (events)
var queryQueue:IQueryQueue = new QueryQueue(mockedQueryTaskFactory);
handleSignal(this, queryQueue.completed, verifyOnCompleted, 500, null);
registerFailureSignal(this, queryQueue.canceled);
// Do it
queryQueue.add(query, "http://test.com");
queryQueue.execute();
// Test that things went according to plan
assertThat(queryQueue.inProgress, isTrue());
verify(mockedQueryTask);
verify(mockedQueryTaskFactory);
function verifyOnCompleted(event:SignalAsyncEvent, passThroughData:Object):void
{
assertThat(queryQueue.inProgress, isFalse());
}
}
メソッドは次のQueryQueue.execute
ようになります。
public function execute():void
{
_inProgress = true;
for each(var queryObject:QueryObject in _queryTasks)
{
var queryTask:QueryTask = _queryTaskFactory.createQueryTask(queryObject.url);
var asyncToken:AsyncToken = queryTask.execute(queryObject.query);
var asyncResponder:AsyncResponder = new AsyncResponder(queryTaskResultHandler, queryTaskFaultHandler, queryObject.token);
asyncToken.addResponder(asyncResponder);
}
}
private function queryTaskResultHandler(result:Object, token:Object = null):void
{
// For each result collect the data and stuff it into a result collection
// to be sent via the completed signal when all querytask responses
// have been processed.
}
private function queryTaskFaultHandler(error:FaultEvent, token:Object = null):void
{
// For each error collect the error and stuff it into an error collection
// to be sent via the completed signal when all querytask responses
// have been processed.
}
queryTaskResultHandler
上記のテスト 6 では、およびで返されるデータqueryTaskFaultHandler
が適切に処理されることをテストします。
つまり、completed
成功と失敗の結果を含むすべてのクエリ応答が返されるまで、イベントをディスパッチしません。
このプロセスをテストするには、モックされた各クエリ タスクの結果ハンドラーとエラー ハンドラーに返されるデータをモックする必要があると思います。
AsyncResponder
では、 FlexUnit を使用して作成された結果ハンドラーに渡されたデータをモック化し、モック化するにはどうすればよいでしょうか。