Flex, Flexunit: How to test that an event is dispatched twice?

别等时光非礼了梦想. 提交于 2019-12-06 00:37:54

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);
}

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!