infinite / mockito-flex

0 stars 0 forks source link

Control the application-domain in which mocks/proxy-classes are created #36

Open infinite opened 9 years ago

infinite commented 9 years ago

I am currently experimenting with testing in a IoC-powered application e.g. with Parsley.

The testing approach involves wiring-up a number of components using DI and the aim is to verify that, while decoupled with messaging, these components can communicate and function as a collective correctly.

I would like to stub service calls with mockito-flex, but seeing as concrete-classes can not be stubbed, the alternative is to inject a mock into the IoC context.

This can be done as far as the API is concerned, but I experience the following error:

{{{

!as3

ReferenceError: Specified ApplicationDomain does not contain the class asmock.generated::DirectoryService3AE89A3CA2BD79921B6AE4B863AB2635D393E7A6 at org.spicefactory.lib.reflect::ClassInfo$/getClassDefinitionByName()[I:\Spicefactory\Parsley\spicelib-reflect\org\spicefactory\lib\reflect\ClassInfo.as:150] at org.spicefactory.lib.reflect::ClassInfo$/getClassInfo()[I:\Spicefactory\Parsley\spicelib-reflect\org\spicefactory\lib\reflect\ClassInfo.as:160] at org.spicefactory.lib.reflect::ClassInfo$/forInstance()[I:\Spicefactory\Parsley\spicelib-reflect\org\spicefactory\lib\reflect\ClassInfo.as:117] at org.spicefactory.parsley.runtime.processor::RuntimeConfigurationProcessor/processInstances()[I:\Spicefactory\Parsley\parsley-config\org\spicefactory\parsley\runtime\processor\RuntimeConfigurationProcessor.as:85] at org.spicefactory.parsley.runtime.processor::RuntimeConfigurationProcessor/processConfiguration()[I:\Spicefactory\Parsley\parsley-config\org\spicefactory\parsley\runtime\processor\RuntimeConfigurationProcessor.as:78] at org.spicefactory.parsley.core.builder.impl::DefaultCompositeContextBuilder/handleProcessor()[I:\Spicefactory\Parsley\parsley-core\org\spicefactory\parsley\core\builder\impl\DefaultCompositeContextBuilder.as:229] at org.spicefactory.parsley.core.builder.impl::DefaultCompositeContextBuilder/invokeNextProcessor()[I:\Spicefactory\Parsley\parsley-core\org\spicefactory\parsley\core\builder\impl\DefaultCompositeContextBuilder.as:205] at org.spicefactory.parsley.core.builder.impl::DefaultCompositeContextBuilder/invokeNextProcessor()[I:\Spicefactory\Parsley\parsley-core\org\spicefactory\parsley\core\builder\impl\DefaultCompositeContextBuilder.as:215] at org.spicefactory.parsley.core.builder.impl::DefaultCompositeContextBuilder/build()[I:\Spicefactory\Parsley\parsley-core\org\spicefactory\parsley\core\builder\impl\DefaultCompositeContextBuilder.as:178] at com.darrenbishop.support.flexunit.parsley::BuildParsleyContext/buildContext()[C:\Dev\workspaces\flex\parsley-flexunit\src\test\flex\com\darrenbishop\support\flexunit\parsley\BuildParsleyContext.as:40] at com.darrenbishop.support.flexunit.parsley::BuildParsleyContext/evaluate()[C:\Dev\workspaces\flex\parsley-flexunit\src\test\flex\com\darrenbishop\support\flexunit\parsley\BuildParsleyContext.as:26] at org.flexunit.internals.runners.statements::StatementSequencer/executeStep()[E:\hudson\jobs\FlexUnit4-Flex3.5\workspace\FlexUnit4\src\org\flexunit\internals\runners\statements\StatementSequencer.as:98] ... }}}

I believe there's a possible workaround in the MockeryProvider SPI mechanism, but seems quite heavy weight.

Is there a simpler way to do this?

infinite commented 9 years ago

From loomis on 2011-04-20 11:51:43+00:00

I think the problems lays somewhere in between what parsley reflection does and how asmock generates mock classes. As far as I'm concerned a mock class is loaded into the ApplicationDomain.currentDomain, possibly there is some discrepancy between this and the domain used by spicelib. You could try debugging a bit and make sure they are the same.

infinite commented 9 years ago

From Darren Bishop on 2011-04-20 12:51:51+00:00

Well I figured it out not long after my original post; it's not an issue with Parsley, which uses concrete classes and supports setting of the app-domain.

The issue is somewhere in asMock; it creates a MovieClip on the fly and loads it dynamically and generates proxies there, so it's as if the mocks are coming from an in-memory SWF. Therefore mocks coming from that dynamic-SWF will have a different idea of what ApplicationDomain.currentDomain is.

I worked around this by implementing my own MockeryProvider, MockCreator and ProxyRepository (asMock).

Please see the files attached.

These get hooked in by a modified MockitoRule implementation, as follows:

{{{

!as3

override public function apply(base:IAsyncStatement, method:FrameworkMethod, test:Object):IAsyncStatement {
    ...
    currentMockito = new Mockito(AsmockADMockeryProvider);}}}
    ...
}

}}}

Note: the same can be done for MockitoRunner.

infinite commented 9 years ago

From loomis on 2011-04-20 14:01:23+00:00

OK sounds good. I'll add something that allows setting the application domain. Thanks for figuring it out!

Regards, Kris

infinite commented 9 years ago

From Darren Bishop on 2011-04-20 17:29:09+00:00

No probs