drewbourne / mockolate

fake chocolate, mock objects and test spies for AS3
http://mockolate.org/
MIT License
145 stars 27 forks source link

Unexpected "ReferenceError: Variable <stubbed class> is not defined" with RemoteObject #15

Closed wolever closed 14 years ago

wolever commented 14 years ago

I'm trying to mock a RemoteObject:

    service = strict(RemoteObject);
    stub(service).method("getOperation").args(anything()).returns(null);
    var x:* = service.getOperation("asdf");

But, on the last line (var x:* = service.getOperation(...)), I get this error:

        ... snip ...
        at tests.global.services::TestService/testRealCallWithError()[.../services/TestService.as:122]
        at asmock.generated::RemoteObject4570E96E984C736EA25B72EBC1E9FFEF3CE48081/getOperation()
        at org.floxy::InterceptorProxyListener/methodExecuted()[.../floxy/InterceptorProxyListener.as:34]
        at org.flemit.reflection::Type$/getType()[.../reflection/Type.as:458]
        at global/flash.utils::getDefinitionByName()
    ReferenceError: Error \#1065: Variable RemoteObject4570E96E984C736EA25B72EBC1E9FFEF3CE48081 is not defined.

I am (I believe) correctly preparing RemoteObject (using prepare(RemoteObject) in conjunction with Async.proceedOnEvent).

Is this a known error? Is there anything I can do about it?

Thanks,
David

wolever commented 14 years ago

Alright, so it looks like this problem is a result of Type.getType calling obj.constructor, which calls AbstractService.flash_proxy::getProperty which calls the AbstractService.getLocalName, which results in a call to InterceptorProxyListener.gethodExecuted which calls Type.getType… And things just go down hill from there.

I've hacked around this by using a subclass of RemoteObject:

package tests.global.services.helpers {

import flash.utils.flash_proxy;

import mx.rpc.remoting.RemoteObject;    

use namespace flash_proxy;

public class StubbableRemoteObject extends RemoteObject {
    override flash_proxy function getProperty(name:*):* {
        if (name is QName && QName(name).localName == "constructor")
                return StubbableRemoteObject;
        return super.flash_proxy::getProperty(name);
    }
}
}

But that leads to another error:

        ... snip ...
        at tests.global.services::TestService/testRealCall()[.../services/TestService.as:103]
        at asmock.generated::StubbableRemoteObject424D059564B73F601F52B2C57FCB1742C6BACFC4/getOperation()
        at org.floxy::InterceptorProxyListener/methodExecuted()[.../floxy/InterceptorProxyListener.as:56]
        at mockolate.ingredients.floxy::InterceptingCouverture/intercept()[.../floxy/InterceptingCouverture.as:40]
        at mockolate.ingredients::Mockolatier/mockolate.ingredients.only::invoked()[.../ingredients/Mockolatier.as:271]
        at mockolate.ingredients::Mockolate/mockolate.ingredients.only::invoked()[.../ingredients/Mockolate.as:179]
        at mockolate.ingredients::MockingCouverture/mockolate.ingredients.only::invoked()[.../ingredients/MockingCouverture.as:683]
        at mockolate.ingredients::MockingCouverture/invokeExpectation()[.../ingredients/MockingCouverture.as:706]
        at mockolate.ingredients::MockingCouverture/findEligibleExpectation()[.../ingredients/MockingCouverture.as:653]
        at global/asx.array::detect()[.../array/detect.as:22]
        at Function/http://adobe.com/AS3/2006/builtin::apply()
        at mockolate.ingredients::MockingCouverture/isEligibleExpectation()[.../ingredients/MockingCouverture.as:670]
        at mockolate.ingredients::Expectation/eligible()[.../ingredients/Expectation.as:268]
        at mockolate.ingredients.floxy::FloxyInvocation/get name()[.../floxy/FloxyInvocation.as:39]
TypeError: Error #1009: Cannot access a property or method of a null object reference.
drewbourne commented 14 years ago

When did you last update Mockolate? I changed FLoxy a few weeks ago to not call obj.constructor when attempting to get the Class reference as constructor may be an explicit property on the proxied objects and not use the implicit implementation that returns the objects constructing Class or Function.

This FlexUnit 4.1 test case works as expected.

package mockolate.sandbox
{
    import mockolate.runner.MockolateRule;
    import mockolate.stub;
    import mx.rpc.remoting.RemoteObject;
    import org.hamcrest.assertThat;
    import org.hamcrest.core.anything;
    import org.hamcrest.object.nullValue;

    public class RemoteObjectTest
    {
        [Rule]
        public var mockolateRule:MockolateRule = new MockolateRule();

        [Mock(type="strict")]
        public var remoteObject:RemoteObject;

        [Test]
        public function shouldWork():void
        {
            stub(remoteObject).method("getOperation").args(anything()).returns(null);
            var x:* = remoteObject.getOperation("asdf");
            assertThat(x, nullValue());
        }
    }
}
drewbourne commented 14 years ago

Closing this as fixed since 0.9.2.