Flex单元测试:测试GUI组件

Flex是一门面向图形用户界面的编程语言,因此,在单元测试中经常需要针对GUI组件编写测试案例。测试GUI组件与测试普通的actionscript对象有所不同:普通的actionscript对象只需要进行对象初始化即可使用,而GUI组件对象则需要添加到界面上方能发挥作用。在FlexUnit中,可以通过UIImpersonator来模拟添加GUI组件:

[Before(ui)]
public function setUp():void {  
    _comp = new CustomGUIComponent();
    UIImpersonator.addChild(_comp);
}

[After(ui)]
public function tearDown():void {  
    UIImpersonator.removeChild(_comp);
    _comp = null;
}

值得注意的是,在Before和After元数据后须注明ui关键词。

即使是使用UIImpersonator来模拟GUI组件的添加,该组件添加过程也需要一定的时间,这对于Test Case的编写是很不利的。以上述代码为例,如果直接编写包含_comp组件操作的Test Case函数,那么该Test Case在运行时大多会报错(“_comp is not ready”)。如何解决该问题呢?

一种方式是在编写组件类的时候,在组件的creationComplete handler函数结束处,dispatch一个Event出来(比如COMP_CREAT_COMPLETE)。而在编写单元测试的时候,等待该事件的触发:

[Before(async, ui)]
public function setUp():void {  
    _comp = new CustomGUIComponent();
    UIImpersonator.addChild(_comp);
    Async.proceedOnEvent(this, _comp, CustomGUIComponent.COMP_CREAT_COMPLETE, 2000); //wait until event is dispatched, with 2 seconds timeout.
}

[After(async, ui)]
public function tearDown():void {  
    UIImpersonator.removeChild(_comp);
    _comp = null;
}

需要注意的是,由于proceedOnEvent是Async类的方法,在Before和After元数据后需声明async关键词。

上述方法可以解决GUI组件添加问题,但却显得不那么自然,并且只适用于自定义组件,如果涉及到对Flex自带组件的添加进行测试,就无计可施了。

更加自然的方式是在模拟添加GUI组件后,等待几秒钟:

private var EVENT_AWHILE:String = "EVENT_AWHILE";

[Before(async, ui)]
public function setUp():void {  
    _comp = new CustomGUIComponent();
    UIImpersonator.addChild(_comp);

    setTimeout(dispatchEventAfterAWhile, 2000);
    Async.proceedOnEvent(this, _comp, EVENT_AWHILE, 3000);
}

[After(async, ui)]
public function tearDown():void {  
    UIImpersonator.removeAllChildren();
    _comp = null;
}

private function dispatchEventAfterAWhile():void  
{
    _comp.dispatchEvent(new Event(EVENT_AWHILE));
}