Flex、Flexunit:如何测试一个事件被调度两次?

发布于 2024-07-27 13:02:37 字数 963 浏览 4 评论 0原文

我正在 Flex 应用程序中测试一些事件调度代码,使用 FlexUnit 的 addAsync 方法来测试事件的调度。 到目前为止,一切都很好,我可以确保至少有一个事件被触发。 不过,我想更详细一点; 我想确保准确地调度我期望的事件集。 是否有一个有用的测试模式(或者甚至不同的测试框架——我很灵活!)来完成这个任务?

我尝试了这段代码,但第二次似乎没有被调用:

protected function expectResultPropertyChange(event: Event, numberOfEvents: int = 1): void {
    trace("Got event " + event + " on " + event.target + " with " + numberOfEvents + " traces left...");
    assertTrue(event.type == ResponseChangedEvent.RESPONSE_CHANGED);
    if (numberOfEvents > 1) {
        event.target.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, addAsync(expectResultPropertyChange, 1000, numberOfEvents - 1));
    }
}

public function testSomething(): void {
    requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, addAsync(expectResultPropertyChange, 1000, 2));
    requiredQuestion.responseSelected("1", true);
    requiredQuestion.responseSelected("2", true);
}

I'm testing some event dispatch code in a Flex app, using FlexUnit's addAsync method for testing that events are dispatched. Great so far, I can ensure that at least one event was fired. However, I want to be a bit more detailed; I want to ensure that exactly the set of events I'm expecting are dispatched. Is there a useful test pattern (or, even, different test framework -- I'm flexible!) to accomplish this?

I tried this code, but it doesn't seem to get invoked the second time:

protected function expectResultPropertyChange(event: Event, numberOfEvents: int = 1): void {
    trace("Got event " + event + " on " + event.target + " with " + numberOfEvents + " traces left...");
    assertTrue(event.type == ResponseChangedEvent.RESPONSE_CHANGED);
    if (numberOfEvents > 1) {
        event.target.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, addAsync(expectResultPropertyChange, 1000, numberOfEvents - 1));
    }
}

public function testSomething(): void {
    requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, addAsync(expectResultPropertyChange, 1000, 2));
    requiredQuestion.responseSelected("1", true);
    requiredQuestion.responseSelected("2", true);
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

花落人断肠 2024-08-03 13:02:37

回应评论...

如果事件被调度怎么办
直接地? 响应选择没有
触发异步事件
复合对象,它只是简单地调度
RESPONSE_CHANGED 事件本身
直接地。 我不明白这是怎么回事
可以使用您的方法来模拟
方法。 请注意,我对
按原样模拟测试实践,所以我
可能缺少一个简单的解决方案
在这里。

..在这种情况下,您不需要使用模拟或 addAsync。 像这样的事情会做:

public function testSomething(): void 
{
    var requiredQuestion : RequiredQuestion = new RequiredQuestion();

    var callCount : int = 0;
    requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, function(event : ResponseChangedEvent)
    {
        callCount++;
    });

    requiredQuestion.responseSelected("1", true);
    requiredQuestion.responseSelected("2", true);

    assertEquals(2, callCount);
}

In response to the comment...

What if the event is dispatched
directly? responseSelected doesn't
trigger an asynchronous event on a
composite object, it simply dispatched
the RESPONSE_CHANGED event itself
directly. I'm not seeing how this
approach can be mocked using your
method. Mind you, I'm fuzzy on the
mock testing practice as-is, so I'm
probably missing a simple solution
here.

..in that case you don't need to use a mock or addAsync. Something like this will do:

public function testSomething(): void 
{
    var requiredQuestion : RequiredQuestion = new RequiredQuestion();

    var callCount : int = 0;
    requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, function(event : ResponseChangedEvent)
    {
        callCount++;
    });

    requiredQuestion.responseSelected("1", true);
    requiredQuestion.responseSelected("2", true);

    assertEquals(2, callCount);
}
累赘 2024-08-03 13:02:37

这将是一个高级示例,说明如何使用进行异步调用的模拟对象来解决类似的问题。 显然我看不到你的代码,所以我无法给你一个准确的例子。

因此,正如我在评论中所说,您可以模拟类中的依赖项来伪造异步调用,以便它们变得同步。 采用下面的类

public class RequiredQuestion extends EventDispatcher
{
    private var someAsynchronousObject : IAsynchronousObject;

    public function RequiredQuestion(someAsynchronousObject : IAsynchronousObject = null)
    {
        someAsynchronousObject = someAsynchronousObject || new AsynchronousObject();
        someAsynchronousObject.addEventListener(Event.COMPLETE, asyncCallComplete);
    }

    public function responseSelected(id : String, flag : Boolean) : void
    {
        //Will asynchronously fire the Event.COMPLETE event
        someAsynchronousObject.startAsynchrounsCall(); 
    }

    protected function asyncCallComplete(event : Event) : void
    {
        dispatchEvent(new ResponseChangedEvent(ResponseChangedEvent.RESPONSE_CHANGED));
    }
}

,因此默认情况下您将使用您想要使用的具体类,除非通过构造函数将 someAsynchronousObjec 注入到该类中。 AsycnhronousObject 可能有它自己的单元测试,或者它位于外部类中,因此您并不真正想要或需要测试其功能。 您现在可以做的是创建一个实现 IAsynchronousObject 的模拟对象,该对象可用于伪造其行为。 使用 ASMock 框架,测试可能如下所示:

public function testSomething(): void 
{
    var mockIAsycnhronousObject :  IAsynchronousObject =
        IAsynchronousObject(mockRepository.createStrict( IAsynchronousObject));

    SetupResult.forEventDispatcher(mockIAsycnhronousObject);
    SetupResult.forCall(mockIAsycnhronousObject.startAsynchronousCall())
        .dispatchEvent(new Event(Event.COMPLETE)); // all calls to the startAsynchronousCall method and dispatch the complete event everytime it's called.

    mockRepository.replayAll();

    var requiredQuestion : RequiredQuestion = new RequiredQuestion(mockIAsycnhronousObject);

    var callCount : int = 0;
    requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, function(event : ResponseChangedEvent)
    {
        callCount++;
    });

    requiredQuestion.responseSelected("1", true);
    requiredQuestion.responseSelected("2", true);

    assertEquals(2, callCount);

    mockRepository.verifyAll();
}

这只是模拟如何帮助您进行单元测试的示例之一。 尽管对于 ActionScript(12 月发布)来说它仍然很新,但关于模拟的信息非常丰富。 ASMock 基于 .net Rhino 模拟,因此如果您需要帮助,搜索 Rhino 模拟应该会得到更多结果。

绝对是一种不同的思维方式,但是一旦你进入它,你就会想知道如果没有它们,你是如何进行单元测试的。

This is going to be a high level example of how a similar problem could be solved using a mocked out object of whatever it is that's doing the asynchronous call. Obviously i can't see your code so i can't give you a precise example.

So, as i said in the comment, you can mock out a dependency in a class to fake asynchronous calls so that they become synchronous. Take the below class

public class RequiredQuestion extends EventDispatcher
{
    private var someAsynchronousObject : IAsynchronousObject;

    public function RequiredQuestion(someAsynchronousObject : IAsynchronousObject = null)
    {
        someAsynchronousObject = someAsynchronousObject || new AsynchronousObject();
        someAsynchronousObject.addEventListener(Event.COMPLETE, asyncCallComplete);
    }

    public function responseSelected(id : String, flag : Boolean) : void
    {
        //Will asynchronously fire the Event.COMPLETE event
        someAsynchronousObject.startAsynchrounsCall(); 
    }

    protected function asyncCallComplete(event : Event) : void
    {
        dispatchEvent(new ResponseChangedEvent(ResponseChangedEvent.RESPONSE_CHANGED));
    }
}

So by default you are using the concrete class that you want to use unless someAsynchronousObjec is injected into the class via the constructor. AsycnhronousObject probably has it's own unit tests or it's in an external class so you don't really want, or need to be testing its functionality. What you can now do is create a mock object that implements IAsynchronousObject that can be used to fake its behavior. Using the ASMock framework the test could look something like this:

public function testSomething(): void 
{
    var mockIAsycnhronousObject :  IAsynchronousObject =
        IAsynchronousObject(mockRepository.createStrict( IAsynchronousObject));

    SetupResult.forEventDispatcher(mockIAsycnhronousObject);
    SetupResult.forCall(mockIAsycnhronousObject.startAsynchronousCall())
        .dispatchEvent(new Event(Event.COMPLETE)); // all calls to the startAsynchronousCall method and dispatch the complete event everytime it's called.

    mockRepository.replayAll();

    var requiredQuestion : RequiredQuestion = new RequiredQuestion(mockIAsycnhronousObject);

    var callCount : int = 0;
    requiredQuestion.addEventListener(ResponseChangedEvent.RESPONSE_CHANGED, function(event : ResponseChangedEvent)
    {
        callCount++;
    });

    requiredQuestion.responseSelected("1", true);
    requiredQuestion.responseSelected("2", true);

    assertEquals(2, callCount);

    mockRepository.verifyAll();
}

This is just one example of how mocking can help you unit tests. There's a whole wealth of info out there on mocking although it is still very new to ActionScript (released in December). ASMock is based on the .net Rhino mocks so searching for Rhino mocks should throw up a lot more results if you need help.

Definitely a different way of thinking but once you get into it you tend to wonder how you got by in unit testing without them.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文