Mock objects and AS3 : Now I really don’t want to use explicit typing
Brian LeGros | October 25th, 2008 | programmingSo in my search for mock object libraries, I continue to run into frustration with explicit typing in ActionScript 3. I did some searching and found a really great mock object library called mock-as3. It’s an expectation based library, in its early stages, but surprisingly featured and intuitive. Here are some usage examples from the author.
I’ve been writing code in ActionScript using explicit types, like most everyone I know who uses AS3, so mock-as3 out of the box won’t meet my needs. If I wanted to begin using interface classes and stubbing out my mocks (as mentioned in the examples) I could, but I won’t; the author even comments that it is extremely tedious to do and doesn’t necessarily advocate it. He hopes to have features in future versions of the library available to handle this but for now they are not available. In general, implementing interfaces for all classes that I’d like to mock is something I don’t agree with in any language. I’m a believer that refactoring your code will make a use case for the use of a programmatic interface over time; there are explicit cases where they are useful, but in the case of mocking, I’m not a big fan.
In any case, I did some thinking and wondered if there was a way to convert an object to a different type at runtime. I figured it’d take some bytecode manipulation, but I’m new to the game, so others much have thought about this already I assumed. Sure enough, I found an implementation by Darron Schall called ObjectTranslator which will convert an object’s type at run-time. I ran through some basic examples and everything worked as expected, so I thought, why not try to convert Mock, which is the class used to mock an object, to the class type passed in at instantiation? The implementation of ObjectTranslator just switches a byte for the new class type and directly copies the bytes of the object into a new byte stream. Worth a shot right?
In mock-as3’s implementation Mock is a subclass of everyone’s favorite class, Proxy. I did a basic test creating an expectation with the same name as the method in my class I wanted to mock and then used ObjectTranslator to convert the mock’s type. I then passed the typed mock to something to consume it and test to see if my expectations return value was given. Below is a the code I wrote:
1 2 3 4 5 6 7 8 9 10 11 | var mock : Mock = new Mock(new MyClass()); trace(describeType(mock)); mock.method("method1").returns("PASS!"); trace(mock.method1()); var newMock : MyClass = ObjectTranslator.objectToInstance(mock, MyClass); trace(describeType(newMock)); var typedUsage : UsageClass = new UsageClass(newMock); trace(typedUsage.method1() == "PASS!"); |
Everything works except the final call to trace() which shows false because the value being returned is “FAIL!”, which is the default value for the method in the class declaration. I thought, well maybe I can add functionality to Mock where on each call to method() or property() I will create a property on the mock with the same name of the property passed in and point it to callProperty or getProperty from Proxy. Mock is declared dynamic after all. I gave it a whirl but no luck, I’m guessing there is something special done with Proxy that when I used ObjectTranslator, didn’t come over. There were also some properties used by Mock that didn’t come over because they were not part of the new type, specifically expectations. Since mock-as3 uses its internal reference to expectations I was hoping I would get this for free, but it didn’t work out from what I can tell. Without a way to eval() the code necessary to create a method signature matching the existing signature in the class declaration, I’m pretty much stumped.
If anyone has any suggestions, I’m all for it, but I kinda threw up my hands and called it a day. The more I play with ActionScript 3, the more it feels like the Flex community is going to have to produce things equivalent to CGLib to do anything flexible with ActionScript3 that is still type-safe (e.g. - mocks, AOP, etc). It sounds like from a thread on FlexCoders that the community really wants a Proxy#newProxyInstance method, so hopefully this will make Proxy a little more useful. I’m not sure, however, if they want to be able to instantiate Proxy at run-time or be able to instantiate a formal target property from Proxy of the target’s type. I’m hoping for the latter, but I’m still new to AS3, so who knows. Back to stubs …
Tags: actionscript, cglib, flex, flexcoders, mock-as3, mock-objects, objecttranslator, proxy, stubs
Related posts

Discussion
November 2nd, 2008 at 10:34 am
I think the problem with typing the object using ObjectTranslator is that all that really does is apply the properties of the dynamic object to an already-loaded Class template instance in the AVM. This is exactly what happens when a Java object shows up fresh from the AMF gateway and wants to be converted to a Flex object. As a result, the only things that will be copied over are the matching object properties; additional behavior from the original class instance will be thrown out the window.
As you know, I’ve personally given up on the AS3 language’s ability to handle dynamic proxies, so I’m working on an AS bytecode generator along the lines of a basic CGLib to try to get around the problem. I’ll be blogging about this as I get my first POC finished.
- max
November 17th, 2008 at 5:45 am
Interesting approach, was worth a shot.
Being able to create Mock instances at runtime from an interface or class is the grail for me & mock-as3. I have investigated generating AS3 bytecode for the mocks however none of the libraries or tools I looked at/ used/ hacked on provided sufficient support for required features. I got close last time I tried, so perhaps I should investigate again seeing as more people are getting interested in testing and mocking in AS3.
November 19th, 2008 at 2:22 pm
@Drew - Thanks for stopping by, I really dig mock-as3, so if you need help finding a way to solve these problems, I’d be happy to help. I know that Max is working on a byte code library to make working abc a lot simpler, maybe he can help you out as well.
Add A Comment