Я пытаюсь написать некоторые модульные тесты для класса, который я пишу во Flex 4.5.1, используя FlexUnit 4 и Mockolate для моей среды тестирования и моделирования соответственно. Я использую as3-сигналы для своих пользовательских событий.
Функциональность, которую я пишу и тестирую, - это класс-оболочка (QueryQueue) вокруг QueryTask класса в ArcGIS API для Flex . Это позволяет мне легко ставить в очередь несколько задач для выполнения. Моя оболочка 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
никогда не вызывается (для действительных запросов)
- Обработка, выполненная в очереди, корректно обрабатывает и упаковывает результаты запроса
Пока что я могу написать тесты для пунктов с 1 по 5, во многом благодаря ответу, предоставленному weltraumpirat. Мой тест выполнения теперь выглядит следующим образом.
[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.
}
Для теста № 6, описанного выше, я хочу проверить, правильно ли обрабатываются данные, возвращаемые в queryTaskResultHandler
и queryTaskFaultHandler
.
То есть я не отправляю событие completed
, пока не будут возвращены все ответы на запросы, включая успешные и неудачные результаты.
Чтобы протестировать этот процесс, я думаю, что мне нужно смоделировать данные, возвращающиеся в результате, и обработчики ошибок для каждой задачи смоделированного запроса.
Итак, как мне высмеивать данные, передаваемые в обработчик результатов, созданный с помощью AsyncResponder
с использованием FlexUnit и mockolate.