Question

I have been working on how to handle an inherited flexunit test that is beginning to fail on faster server builds. The MyMockService is not getting prepared before the unit test begins to run. We are using FlexUnit and Mockolate.

<failure 
    message="A proxy for com.something.somemock.service::MyMockService has not been prepared yet" 
    type="com.something.somemock.MyAsyncTest">ArgumentError: A proxy for com.something.somemock.service::MyMockService has not been prepared yet.
    //... (lots removed here)
</failure>

Generic imports being used:

import flash.events.Event;
import flexunit.framework.Assert;
import mockolate.nice;
import mockolate.prepare;
import mockolate.stub;
import mockolate.verify;
import org.flexunit.async.Async;
import flash.utils.Timer;
import flash.events.TimerEvent;

Here's a stub of the code. The (I think) important parts are there so you get the gist.

public class MyAsyncTest
{

    [Before(async)]
    public function prepareMockObjects():void
    {
        Async.proceedOnEvent(this, prepare(MyMockService), Event.COMPLETE);
    }

    [Test(async)]
    public function testExecute():void
    {

        var service:MyMockService = nice(MyMockService);
        verify(service).method("runSomething").args(ArgumentBuilder).once();

    }
}

After doing a lot of work changing timeouts and adding sleep methods (all useless in battling the error) I have introduced one more test to the flexunit test class that contains only a delay. I ordered the tests and am finding that my test now passes every time. (this is good) I just really hate putting a test in just so that I get the three second delay I need for the prepare to finish.

Here's the code stub for visuals:

public class MyAsyncTest
{   
    protected function makeMeSleep(howLongMs:int):void
    {
        //timer code to sleep
    }

    [Before(async)]
    public function prepareMockObjects():void
    {
        Async.proceedOnEvent(this, prepare(MyMockService), Event.COMPLETE);
    }

    [Test(async, order=1)]
    public function delayTheNextTest():void
    {
        var hasPaused:Boolean = makeMeSleep(3000);
        Assert.assertTrue("This is a silly delay to allow the service to prepare", true);
    }

    [Test(async, order=2)]
    public function testExecute():void
    {
        var service:MyMockService = nice(MyMockService);
        verify(service).method("runSomething").args(ArgumentBuilder).once();        
    }
}

I'm glad to have the test now build up as it should, but it FEELS dirty. It has always been my assumption that the [Test] block will not run until the [Before] block has finished but that doesn't seem to be the case in this testing condition. I guess one important take away from you folks for me would be whether this test is in poor style the way my mock service is being prepared, and what would be a better way that would avoid adding a "sleep" test just to buy time? (poor style in and of itself IMHO)

thanks for your input in advance.

Was it helpful?

Solution

I have run into similar issues with Mockolate, and I seem to remember reading an answer by Drew that mentioned he is aware they exist.

I have found rules to be reliable for async tests, and using them makes the code more readable, as well. Just declare both the MockolateRule and the desired mock objects as a member variable (must be public for the metadata to be picked up correctly, and make sure to instantiate the rule!), then use with mock() as you would nice() otherwise.

[Rule]
public var myRule:MockolateRule = new MockolateRule();

[Mock]
public var myService:MyService;

[Before]
public function setUp():void {
    myService = mock(MyService);
}

[Test]
public function test():void {
    assertNotNull(myService);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top