Thursday, February 18, 2010

Can FlexUnit4 test Parsley applications?

One of the challenges you face when adopting a dependency injection framework for Flex development is how to test classes that use features of the DI framework. For example when you use the Parsley framework a Command class is typically implemented as follows:-

Here the command dispatches a CommandCompleteEvent message when the service returns a result using Parsley's MessageDispatcher. If you want to test this implementation you need to be able to write a test class that can handle Parsley's CommandCompleteEvent message. You'd probably write the test class like this:-

and you'd probably run it in the normal way as follows:-

Sadly since the test class is not in the Parsley context the [MessageDispatcher] and [MessageHandler] decorators are ignored, the test will never run the command and the test will always fail. Additionally you probably want to be able to [Inject] the test classes dependencies rather than instantiating them programatically in the setUp method. Clearly for this work the test class needs to be a "managed" object (i.e. an object in the Parsley context). It's easy to put the test class into the context but getting FlexUnit4 to use the managed object is easier said than done. What we really need is a Parsley-aware test "runner" (like Spring Java's context-based test runner) that you could use as follows:-

but unfortunately at the time of writing there's no such Parsley test runner.

If you declare the test class in a Parsley ApplicationContext.mxml and instantiate it using Parsley's FlexContextBuilder, the Parsley [MessageDispatcher], [MessageHandler] and [Inject] decorators will work but the challenge is to get FlexUnit4 to use the "managed" instance of the test class. Unfortunately the way FlexUnit4 works at the moment you specify the class names of the test classes to FlexUnit4 and FlexUnit4 goes off and creates its own instances of the test classes. Major disconnect.

If you take a look under the hood of FlexUnit4 you'll find that the parameters to FlexUnitCore's run method can be instances as well as classes. So you might expect the following to work:-

but don't try that at home because this undocumented feature of FlexUnit4 isn't fully implemented yet and it doesn't work. That's a shame since this would make FlexUnit4 much easier to use with dependency injection frameworks.

Time to give up? The good news is that Parsley 2.2 includes support for generic "short-lived" objects (originally included to support the command pattern) that we can leverage to insert the test class into the Parsley context programatically with createDynamicContext().addObject(this). The following works:-

I guess one day we might have test runner support in Parsley and Spring ActionScript. Until then I guess we have to make do with these workarounds.

When is a Cairngorm command not a command?

Answer: When it's a Cairngorm 3 command

Cairngorm 2, notwithstanding the architectural weaknesses it inherited from EJB2, included an implementation of a pattern that's become widely used in Flex applications; the command pattern.

In this patten a command object is used to represent a request to perform a unit of work. Typically in a Flex application command instances represent calls to the service layer on the server where each command object stores the paramenters to perform its unit of work. Since Flex's I/O framework is fully asynchronous, several requests to the same operation on the service layer may be be underway at the same time. The command pattern with a separate instance for each request provides a elegant way to manage concurrency in a Flex application. In a Cairngorm 2-based Flex application, each time you dispatch a Cairngorm event, a fresh instance of the event's corresponding command object is created by the Cairngorm framework. If the same Cairngorm event is dispatched again while the first operation is still in progress you'll end up with another instance of the same command, each one representing a specific call, each with its own specific parameters.

As a conseqeunce of this design Cairngorm 2-based applications can safely assume that each command object is specific to each request and may store state in instance variables of the command object. That’s a safe assumption since that’s how the command pattern is defined.

One of the most remarkable features of the collection of libraries that Adobe have chosen to call “Cairngorm 3” is that it doesn't provide an implementation of the command pattern. In Cairngorm 3's "integration library" (implemented as a Parsley extension), commands are now singletons that are re-used by concurrent requests. While in many cases Flex applications will ensure the serialization of requests to the same operation, in general this means that applications written for Cairngorm 2 can't be easily migrated to Cairngorm 3. Cairngorm 3 simply doesn't provide an implementation of the command pattern that's compatible with previous versions of Cairngorm. In fact it doesn’t provide an implementation of the command pattern at all. Worse still the [Command] decorator is used in Cairngorm 3 to decorate these singletons implies that these decorated classes are implementations of the command pattern when they’re not.

Parsley appears to have replicated this mistake in its most recent release (2.2) which now also supports the [Command] decorator to decorate these singletons. This decorator would have been better named [Operation] or something else that doesn’t imply that the decorated class is an implementation of the command pattern. The good news is that the latest release of Parsley does provide an implmentation of the command pattern in what it calls “short-lived commands" and “dynamic commands”. These “dynamic commands", like in Cairngorm 2, are created each time a request event is handled. Unfortunately Cairngorm 3 doesn’t currently support Parsley’s implementation of the command pattern yet so if you’re thinking of upgrading an existing Cairngorm 2 application to Cairngorm 3 I’d think twice about using Cairngorm 3 in its current state.

If you’re keen to add presentation models to an existing Cairngorm 2 application while leveraging a dependency injection framework (to get rid of all the references to Model.getInstance() etc…), then Spring ActionScript is a great choice since (ironically) it includes much better support for Cairngorm 2’s command pattern (in its optional Cairngorm 2 support library) than Cairngorm 3.