24.7.处理测试用例事件

24.7.1. 问题
我需要等待TestCase中的某个事件。
24.7.2. 解决办法
使用addAsync FlexUnit方法
24.7.3. 讨论
TestCase的测试行为经常会出现等待异步事件问题。如果TestCase方法只涉及同步事件,比如当改变属性时property change事件立即触发,不需要特殊的处理。但是当涉及到异步事件时你就要特别小心了。一般需要在测试中监听异步事件, 如URLLoad 是否完成或UIComponent 是否已创建完毕。这一节将讨论在TestCase中使用URLLoad类和假设的配置对象时如何处理事件。

在TestCase中事件需要被特别对待,因为除非FlexUnit被通知需要等待一个事件,否则测试方法将会理解完成。FlexUnit会认为该方法已通过测试,并开始运行下一个测试方法。这将会导致不一致的结果,如FlexUnit会显示一个绿色状态栏而后台的测试却是失败的或更糟的是会显示错误信息。

需要先通知FlexUnit应该等待触发的事件完成后再决定一个测试是通过还是失败,传递给addEventListener的监听器必须替换为addAsync,addAsync的前两个参数时必须的,剩下的都是可选的,第一个参数是监听器,当事件触发时被调用。第二个参数为单位为毫秒的超时时间,当超过这个时间事件还没触发,FlexUnit将认为该测试失败并继续运行其他的测试方法。

下面的例子是典型的addAsync用法:
+展开
-ActionScript
package
{
import flash.events.Event;
import flash.net.URLLoader;
import flash.net.URLRequest;
import flexunit.framework.TestCase;
public class ConfigurationTest extends TestCase
{
public function testParse():void
{
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE,
addAsync(verifyParse, 1000));
urlLoader.load(new URLRequest("sample.xml"));
}
private function verifyParse(event:Event):void
{
var configuration:Configuration = new Configuration();
assertFalse(configuration.complete);
configuration.parse(new XML(event.target.data));
assertTrue(configuration.complete);
}
}
}

Configuration的parse方法被分为两个方法,第一个方法为等待事件所需的对象进行构造并初始化动作。第二个验证方法则使用事件结果执行处理过程和进行断言。通常情况下,verifyParse方法应该是直接作为addEventListener的监听器参数的,但是这里却被addAsync和给出的1000毫秒超时有包装了一次。请注意这里的监听器函数的名称不是以test开头的;如果是这样的话,那FlexUnit就会试图把它作为额外的测试方法来运行,这可不是我们所期望的结果。

对于FlexUnit来说事件类型是很重要的。且目标监听器可被强制转换为其参数规定类型。上面的例子中使用了通用的Event而不是FlexEvent或其他Event子类,这样监听器可安全地确认其参数类型。不会发生事件不匹配,在运行时会报告这种类型强制转换故障。

在这一点上,关于addAsync有两个需要特别注意的问题。首先,决不能出现同时有两个addAsync处于等待状态,这样FlexUnit将不能正确处理检测和测试。不过把这些AddAsync调用串联起来是可以的,这样只有一个addAsync调用监听器,新的addAsync将在随后的代码中被创建。其次,在测试期间不能多次调用addAsync。因为addAsync机制是作为汇合点让FlexUnit知道何时测试会完成或失败,多次调用addAsync会导致误报或不正常现象。

用addAsync来代替使用闭包或创建实例变量,这样通过addAsync的可选的第三个参数传递给监听器。传递的参数可以是任意的,可灵活使用。例如,上面代码的定义的测试可以在创建确认完成标志Configuration对象之前先初始化XML载入。这样的做法是遵循单元测试的快速故障检测模式,帮助你尽可能的节省整个测试集合的测试时间。下面是使用传递数据的方式修改的测试方法:
+展开
-ActionScript
public function testComplete():void{
var configuration:Configuration = new Configuration();
assertFalse(configuration.complete);
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE,
addAsync(verifyComplete, 1000, configuration));
urlLoader.load(new URLRequest("sample.xml"));
}
private function verifyComplete(event:Event,
configuration:Configuration):void
{
configuration.parse(new XML(event.target.data));
assertTrue(configuration.complete);
}

测试方法中创建的对象作为verifyComplete的第二个参数被传递进来。使用这种机制还可以传递通用的Object或想int这样的基本数据类型。

默认,超过指定的时间后事件将不会被触发,FlexUnit生成失败报告。如果事件没有触发打还有些事情需要处理,这时可以使用addAsync的第四个参数指定将被调用的函数。当测试期间事件没有触发或在测试中执行特殊的对象清理时定义自定义失败处理函数是非常有用的。

自定义失败处理函数总是接受传递的数据,即便它是null。下面我们假设没有触发complete事件来测试下Configuration对象:
+展开
-ActionScript
public function testCompleteEvent():void
{
var configuration:Configuration = new Configuration();
assertFalse(configuration.complete);
configuration.addEventListener(Event.COMPLETE, addAsync(verifyEvent, 250, configuration,
verifyNoEvent));
}
private function verifyEvent(event:Event,configuration:Configuration):void{
fail("Unexpected Event.COMPLETE from Configuration instance");
}
private function
verifyNoEvent(configuration:Configuration):void
{
assertFalse(configuration.complete);
}

还是很有必要为此事件定义一个监听器,如本例所示,当事件触发时,它显示错误状态,当事件没有触发时,自定义失败处理函数仍然会在适当的状态确认Configuration。

为建立或测试一个对象如果有多个异步事件触发,要保证同一时刻只有一个addAsync处于活动状态,如前所述,为了解决此限制,你可以创建另一个addAsync。扩充前面的例子,如果configuration的解析需要载入外部文件,complete状态可能不会立即发生变化。下面的例子就是演示如何把两个事件串联起来:
+展开
-ActionScript
public function testComplexComplete():void
{
var configuration:Configuration = new Configuration();
assertFalse(configuration.complete);
var urlLoader:URLLoader = new URLLoader();
urlLoader.addEventListener(Event.COMPLETE,
addAsync(verifyComplexParse, 10 00, configuration));
urlLoader.load(new URLRequest("complex.xml"));
}
private function verifyComplexParse(event:Event,
configuration:Configuration): void
{
configuration.addEventListener(Event.COMPLETE,
addAsync(verifyComplexComplete, 1000, configuration));
configuration.parse(new XML(event.target.data));
assertFalse(configuration.complete);
}
private function verifyComplexComplete(event:Event,
configuration:Configuration):void
{
assertTrue(configuration.complete);
}

在verifyComplexParse函数是为第一个addAsync进行配置,第二个调用addAsync是为监听串联事件中的下一个事件,这样的串联可以根据需要继续增加事件。

加支付宝好友偷能量挖...


评论(0)网络
阅读(90)喜欢(0)flash/flex/fcs/AIR