Существует одно различие, в котором можно связать пользовательские события с помощью второй формы, которую Вы имеете. Иначе они, кажется, синонимичны. См.: Документы События jQuery
Хороший вопрос.
В модульном тестировании этот подход имеет смысл, но для интеграционного тестирования вы должны тестировать реальную систему, как она будет вести себя в реальной жизни. Это включает в себя любые асинхронные операции и любые побочные эффекты, которые они могут иметь - это наиболее вероятное место для появления ошибок, и, вероятно, вам следует сосредоточить свое тестирование, а не исключать его .
Я часто использую подход "waitFor", при котором я опрашиваю, был ли получен ответ, и таймаут через некоторое время, если нет. Хорошей реализацией этого шаблона, хотя и специфичной для Java, вы можете понять суть, это JUnitConditionRunner . Например:
conditionRunner = new JUnitConditionRunner(browser, WAIT_FOR_INTERVAL, WAIT_FOR_TIMEOUT);
protected void waitForText(String text) {
try {
conditionRunner.waitFor(new Text(text));
} catch(Throwable t) {
throw new AssertionFailedError("Expecting text " + text + " failed to become true. Complete text [" + browser.getBodyText() + "]");
}
}
У нас есть ряд автоматических модульных тестов, которые отправляют асинхронные запросы и нуждаются в проверке вывода / результатов. То, как мы с этим справляемся, заключается в том, чтобы на самом деле выполнять все тестирование, как если бы оно было частью реального приложения, другими словами, асинхронные запросы остаются асинхронными. Но тестовая оснастка действует синхронно: она отправляет асинхронный запрос, находится в спящем режиме [до] определенного периода времени (максимум, в течение которого мы ожидаем получения результата), а если результат все еще недоступен, то тест провалился. Существуют обратные вызовы, поэтому почти во всех случаях тест пробуждается и продолжает выполняться до истечения тайм-аута, но тайм-ауты означают, что сбой (или изменение ожидаемой производительности) не остановит / остановит весь набор тестов.
Это имеет несколько преимуществ:
. Последний пункт может потребовать небольшого объяснения. Тестирование производительности важно, и его часто не учитывают в планах тестирования. То, как выполняются эти модульные тесты, в конечном итоге занимает намного больше времени (время выполнения), чем если бы мы изменили код так, чтобы все выполнялось синхронно. Однако таким образом производительность проверяется неявно, и тесты более точно соответствуют их использованию в приложении. Кроме того, вся наша инфраструктура очередей сообщений тестируется «бесплатно» в процессе.
Что вы тестируете? Поведение вашего класса в ответ на определенные раздражители? В каком случае не подходят подходящие макеты?
Class Orchestrator implements AsynchCallback {
TheAsycnhService myDelegate; // initialised by injection
public void doSomething(Request aRequest){
myDelegate.doTheWork(aRequest, this)
}
public void tellMeTheResult(Response aResponse) {
// process response
}
}
Ваш тест может делать что-то вроде
Orchestrator orch = new Orchestrator(mockAsynchService);
orch.doSomething(request);
// assertions here that the mockAsychService received the expected request
// now either the mock really does call back
// or (probably more easily) make explicit call to the tellMeTheResult() method
// assertions here that the Orchestrator did the right thing with the response
Обратите внимание, что здесь нет истинной асинхронной обработки, и сам макет не должен иметь никакой логики, кроме как разрешить проверку получения правильный запрос. Для модульного тестирования Orchestrator этого достаточно.
Я использовал этот вариант идеи при тестировании процессов BPEL в WebSphere Process Server.