Thursday, January 07, 2016

Darren on the JVM: Scala: Null Coalescing Operator for Scala

Null (Safe|Dereferencing|Coalescing) Operator

I stumbled on to this concept a while ago when researching the many cool features of Scala. I had come across it before, as I’ll mention, but not so concretely. There is a wealth of information on SO and Wiki, which again leaves mythed why Java (my roots) does not support this.

Anyway, what I offer here - which btw is not new - is slightly different to the normal NCO as found in many other languages, for which it is a supported langauge feature.

Note, NCO is supported implicitly by a wider set of laguages i.e. those where every value or expression has a truth value: any value can be coerced to True or False, after which you defer to logical operators; I found this to be the case in ActionScript (I used to be a Flex developer) and is also the case with Bash, where booleans are applicable.

Having read a few SO posts and seeing what others have put out there, I figured I would have a go at implementing a NCO, seeing what features of Scala can be utilized and how far I can take it.

The aim is to get from this

to this

And just for emphasis, compare the amount of horizontal scrolling you have to do to read those code snippets.

Maybe Null, Maybe Not… It’s Optional

Scala offers Option, Try and Either as ways to program with null and exceptions. Using these aren’t quite the same as programming defensively as the null-check is done automatically under-the-hood. However, like most things Scala, it is a noteworthy paradigm shift… that is, going from Null Programming to Option Programming.

While Option, its various composition functions and pattern matching are cool for handling null, given checking for null is so common in OO (or at least Java), it’s a little surprising that there isn’t seamless support for crossing over from the Null-world to the Option-world in Scala (… presumably seeking to succeed where Java fails).

There is the PartialFunction[A, B].lift which helps, but it only goes one-level deep: the benefit is lost if you are required to use a library with a complex Option-less object model; think of some legacy Java library that does not make use of Options, you may as well stick to defensive programming with null-checks.

Extension Methods a.k.a. Implicits

Thanks to Scala’s extension methods i.e. implicit type conversions, the crossover from null to Option is made very easy.

While we haven’t defined any extension methods explicitly, any function of Option is now available to clients of E.

We could at this point use the familiar composition functions on Option, but we want some nice operator syntactic sugar… it’s all about the sugar!

So taking the idea a step further, we introduce an intermediate wrapper class - a facade if you like - to provide these operators and translate them onto Option compositon functions.

So let’s start again with

What we produce is a very concise way to dereference null and chain a sequence of HOFS together: with this we can drill down into the object graph, evaluating to the targeted value or expression; or to None if null is encountered anywhere along the way.

Here is an excerpt from a ScalaTest spec I wrote while exploring all this:

Here you see an example each for passing functions and passing lambdas (anonymous functions); the latter turns out a little unfortunate with all the programming punctuation.

Nonetheless it works! At this stage we are free to match { ... } or map { ... } and so on.

We can extends NSCOps to include a whole raft of convenience operators.

One very cool addition would be performing value checks, that is, for values other than null

How cool is that; all operators continue down the chain if the option is not None and:

  • ?~ the filter expression evaluates to true
  • ?? the non-None value matches the by-name (lazy) operand
  • ?! the non-None value does not match the by-name (lazy) operand

The by-name operators are probably more useful after the Immutable paradigm shift where case classes are the norm, for which == does the right thing.

Since originally posting, I have made edits to reference the published gist which you can see in it’s entirety here.

PLEASE take note of the non-contiguous line numbers here in the post; the Gist integration I use lets you select line number ranges to show, but does not make it obvious to the reader ellipses would have been nice. Please copy-paste from the gist.

Wednesday, January 06, 2016

Darren on the JVM: Scala: Timely Type-Classes Brings Rails-style Date Arithmetic

For those of you who have ever done any Ruby development on Rails super-charged with ActiveRecord (as I recall back from 2008), you would have been blessed with the most intuitive date-arithmetic facility known to programming-man.

At that time in my life, Java was my main bread-and-butter and I longed for this simplicity… I am sure we all did.

Why it did not exist was simple: primitives such as int and String had these binary operators, as supported by the Java language, but of course Objects like java.util.Date did not; to get them would obviously require a change to the language, but where would you draw the line? What would be the default java.lang.Object behaviour in a obj1 + obj2 = ??? situation?

Then came a long Scala: read ‘…change in the language’ becomes ‘… change the language’

Writing Without Punctuation

Before getting into the main meat of this post, let’s digress for a moment to recall another cool and important feature of Scala.

We know binary operators in Scala are just single-parameter functions in disguise. So flipping that on its head, we can use single-parameter functions like operators:

"Scala" concat "Is" concat "The" concat "Bees" concat "Knees"

is exactly the same as

"Scala".concat("Is".concat("The".concat("Bees".concat("Knees"))))

Try them both in sbt console

There are some quirks and special steps to be taken if intermixing alphanumeric characters and symbols in your function names, but you get the gist.

So basically Scala allows us to remove punctuation around function invocations, when those functions are single-parameter functions; you can still remove the . (dot) in invocations of functions with multiple parameters, but the parentheses are still required (…why? Off topic!)

Now exposing binary operators for what they, it stands to reason they can be overriden… or more importantly, can be defined where once they were not.

Extension Methods a.k.a. Implicits

Extension methods are a language feature I discovered when consulting on a C# project Germany many years ago. I remember thinking how cool they were back then and still think they are awesome now in Scala.

Other languages support this feature in their own form too: Ruby has monkey-patching and JavaScript has prototype augmentation. I suppose if you are really desperate for this facility in Java, one can introduce Aspects.

Of course in Scala they are merely an application of implicits, or more accurately, the use of implicit type-conversion.

// Runnable in 'sbt console'
import java.util.Date

implicit class SuperfluousDate(date: Date) {

  def someSuperfluousFunction = date.toString
}

case class UnimaginableDate(date:Date) {

  def someUnimaginableFunction = date.toString
}

implicit def toTheUnimaginable(date:Date) = UnimaginableDate(date)

val now = new Date

now.someSuperfluousFunction

now.someUnimaginableFunction

As with C# and Extension Methods, one needs to be careful with how implicit type-conversion is applied, so to preserve the semantic/conceptual/behavioural integrity of the class being extended.

Type Classes a.k.a. Implicits²

Type classes are a powerful feature that allows Scala developers to define an interface to capture the behaviour to be added to a class. That type-class can then be used to declare dependencies and expectations in other classes.

An out-of-the-box example of this is Scala’s Ordering[T] trait: collections have both min() and max() functions, for example; they only work for the collection, say of type List[A], if there is an implementation of Ordering[A] in implicit scope.

Note type-classes are typically defined as traits and are always parametric, that is, they are defined with a parameter type, [T]; they typically have many - at least one, to be useful - concrete implementations that are case-objects and specify [T].
This is a key difference of the application of simple extension methods, which require a concrete class, as above, that is not a case-object and can work without parameter-types.

The function definitions therein also differ, where it is typical in type-classes to define the first parameter as the this object of the function.

// ...continued
trait Chrono[T] {

  def now: T
  def toMillis(t: T): Long
  def fromMillis(millis: Long): T
  def -(t: T, duration: FiniteDuration): T
  def +(t: T, duration: FiniteDuration): T
}

implicit case object DateChrono extends Chrono[Date] {

  def now = fromMillis(System.currentTimeMillis())
  def toMillis(date: Date) = date.getTime
  def fromMillis(millis: Long) = new Date(millis)
  def -(date: Date, duration: FiniteDuration): Date = new Date(date.getTime - duration.toMillis)
  def +(date: Date, duration: FiniteDuration): Date = new Date(date.getTime + duration.toMillis)
}

As you can see, the type-class Chrono[T] is parametric in [T] and the concrete case-object implementation, DateChrono, specifies [T] to be [Date].

The usefulness of this is perhaps still not apparent

// ...continued
import scala.concurrent.duration.{FiniteDuration, DAYS}

val later = DateChrono.+(now, FiniteDuration(10, DAYS))

later.someUnimaginableFunction

Implicits * (1 + Implicits)

Now we combine the basic implicits, as used to implement extensions methods, with the advanced implicits, to define type-classes, to give us the ActiveRecord-style data-arithmetic sugary goodness

// ...continued
implicit class ChronoArithmetic[T](t: T)(implicit ev: Chrono[T]) {

  def plus(duration: FiniteDuration) = ev.+(t, duration)
  def +(duration: FiniteDuration) = plus(duration)
  def minus(duration: FiniteDuration) = ev.-(t, duration)
  def -(duration: FiniteDuration) = minus(duration)
}

now + FiniteDuration(10, DAYS)

and more sugar

// ...continued
val days20 = FiniteDuration(20, DAYS)

now + days20

and yet more SUGGGAAAARRR

// ...continued
import scala.concurrent.duration._

now + 30.days

How cool is that!

Perhaps there was a bit of a leap there: deciphering ChronoArithmetic, it offers an implicit conversion of instances of type [T] but only where there is an implementation of Chrono[T] available in implicit scope.

It doesn’t end there…

Testing With ChronoTime

Now you may wonder how this applies to testing: have you ever been in the situation where you wanted to set when now is?

Say in a batch of time sensitive tests, by virtue of covering time sensitive production code, where you must have the test code and the production code reliably agree on when now is, down to the microsecond.

You can’t monkey around with the system time as that will break with parallelized testing… and probably break a whole bunch of other things.

Joda-Time offers a mechanism to do this with DateTimeUtils.setCurrentMillisFixed(long), made thread-safe with DateTimeUtils.setCurrentMillisProvider(DateTimeUtils.MillisProvider millisProvider) … which is cool if you are already using Joda-Time and can ensure that all past and future requests for the current time is made via DateTimeUtils.currentTimeMillis() and not the typical System.currentTimeMillis().

An old colleague of mine faced this exact problem and enhanced the implementation with a clock!

// ...continued
trait Clock {
  def millis: Long
}

Now this is essentially the same as DateTimeUtils.MillisProvider. Originally, the API was updated such that an instance of this Clock was explicitly passed around wherever now was needed.

// ...continued... but hold off pasting this in
trait Chrono[T] {
  def now(clock: Clock) = fromMillis(clock.millis)
  ...
}

def rightNow[T](clock: Clock)(implicit ev: Chrono[T]): T = ev.now(clock)

It seemed a shame to litter the API with the introduction of this new Clock class, but that was easily remedied by making it implicit also.

// ...continued... go ahead and paste this in (update Chrono[T])
trait Chrono[T] {
  def now(implicit clock: Clock) = fromMillis(clock.millis)
  ...
}

def rightNow[T](implicit ev: Chrono[T], clock: Clock): T = ev.now

The implementation of now(...) is now (ha) completed provided by Chrono[T]; it is no longer an abstract method and can be removed from all type-classes, such as DateChrono.

Notice how implicit parameters are automatically in implicit scope for invocations made inside the function body; this has the effect that implicit parameters get passed along.

Another quick digression to bring to mind another cool feature of Scala and application of it.

Have Your Slice of Cake

In Scala, it is very common to implement the Cake pattern and compose the execution environment with layers, whether that be the production execution environment or the test execution environment.

The Cake pattern is made possible by Scala’s Traits language feature.
In some ways Scala Traits are similar to Aspects in Java. That said, I have only ever seen Aspects used to augment behaviour; Scala Traits can mixin behaviour AND mixin state - the latter along with Scala’s self-type are utilised in implementing the Cake pattern.

The Cake pattern and layering is really beneficial in that it provides an environment and object-graph that is type-checkable at compile-time; compare that to the dynamic nature of Spring-powered dependency-injection – you know if the Scala + Cake compiles, all dependencies are satisfied.

Execution Environments

Lets introduce a Clock implementation that defers to the system time

// ...continued
trait ClockProvider {

  implicit val clock: Clock
}

case object SystemClock extends Clock {
  def millis = {
    System.currentTimeMillis
  }
}

trait SystemClockProvider extends ClockProvider {

  implicit val clock = SystemClock
}

This implementation can be used to compose an object graph in a production environment

// ...continued
class Main extends SystemClockProvider {
  self: ClockProvider =>

  val now: Date = rightNow[Date]
}

val then = new Main().now

val later = then + 20.days

For testing, we can provide an alternate implementation that always returns the same value

// ...continued
class Production(implicit clock: Clock) {

  println(clock.getClass)
  
  def get5SecondsLater = rightNow[Date] + 5.seconds
}

case object FixedClock extends Clock {
  def millis = {
    0 // since Unix Epoch, 1st January 1970
  }
}

class FixedClockTest extends FixedClockProvider {
  self: ClockProvider =>
  
  val later5Seconds = rightNow[Date] + 5.seconds
  
  val prod = new Production

  assert(prod.get5SecondsLater == later5Seconds, "FAIL")
}

new FixedClockTest

Here’s a negative test using the SystemClock

// ...continued
class SystemClockTest extends SystemClockProvider {
  self: ClockProvider =>
  
  val later5Seconds = rightNow[Date] + 5.seconds
  
  println("Sleeping...")
  
  Thread.sleep(5000)
  
  val prod = new Production

  val prodLater = prod.get5SecondsLater
  
  assert(prodLater != later5Seconds, "FAIL")
}

new SystemClockTest

That’s about it.

Feel free to copy paste from here; there is now also a Gist including a ScalaTest spec available here

Thursday, April 16, 2015

Darren on the JVM: Java and Scala with IntelliJ's Compile Server

PROLOGUE

I went searching YouTrack, doing my due diligence, for an issue (described below) before raising a feature request for IntelliJ's Compile Server facility.

I came across this issue, which describes slow compilation despite having the compile server enabled.

I echo here my comments and findings

If you are trying to make use of IntelliJ's Compile Server facility, say, to make you Red, Green... Refactor cycle go really fast, but can't seem to make it work or observe any speed gains, you may have overlooked an important step.

If when you make a change and click Run or press Shift+F10 and IntelliJ proceeds to 'make' your project, this applies to you.

The problem isn't to do how the Compile Server is configured; it has everything to do with your run configurations.

When you right-click a test or 'main' class, amongst other things, you have the option to 'Create Run Configuration' or 'Run' or 'Debug'; the first option creates a run configuration and pops-up a form to make changes before saving it (does not actually run it), where as the last two create run configurations for you implicitly, which IntelliJ reuses if you attempt to re-run/debug the same package/class/method element again later.

In ALL cases, not just these three, run configurations are created from a list of default configurations. The default for these three cases and many others, include the 'make' Before launch task.

This can be easily verified by playing around with the defaults and making implicit run configurations by right-clicking stuff as per normal.

But to address the slow compilation:

  1. Modify the default templates for the run configurations of interest - I changed Application, JUnit Test, Scala Console, ScalaTest and Spec2 - and removed the 'make' entry in the 'Before launch' section.
  2. Edit your existing run/test configurations, also removing the 'make' 'Before launch' section.

Unless you explicitly change your configuration defaults, right clicking on a test and selecting run will always generate a configuration with the 'make' task present.

Having just read all the blog posts from IntelliJ regarding the Compile Server and SBT's source-base change analysis, they clearly forgot to mention this important step.

Once removed, you can see when clicking Run the test runner starts spinning up immediately (assuming you're trying to run tests).

The only issue I have seen here (I have searched YouTrack for a mention of it to no avail) is if you make a change and hit Run or Shift+F10 immediately, the test runner might fail as the test class is momentarily not on the classpath, that is, in that brief window between detecting the change and the compile server doing its thing.

However, clicking Run (Shift+F10) normally succeeds on the second attempt and it is still infinitely faster than waiting for a needless make to complete.

Now my IntelliJ seems truly amazing

Wednesday, February 25, 2015

Darren on Blogger: Pagination for Blogger powered by jQuery

UPDATE: Replaced all uses of the pagelist class with pagelinks, as depending on the template used, Blogger may or may not use this class to manage its 'blog pages' i.e. tabs.

Some time ago I wrote a 6 part blog and I have very recently written another multi-part blog that has the potential to be quite long.

Once I have done the technical work for a blog post and start writing it up, if it becomes unwieldy, I split it into parts to make it more digestible for the reader.

I observe that different parts receive different levels of traffic, which I take to mean either some parts aren't all that interesting or, put another way, in the era of the internet age, readers seek out the information they want specifically and nothing else.

But for a while now, people who get a lot of traffic on their blog are choosing to monetize their published intellectual property, whether it be with AdSense or Amazon book lists or whatever.

I'm no SEO or click-stream expert, but obviously there's a big difference between an e-Commerce site and the blog of an individual containing all sorts of ramblings; you'd expect e-Commerce sites to be more cohesive, but blogs not necessarily so.

Whatever your online presence, you might find a trade-off between time spent on a page vs. bounce-rate.

Again, while not being an expert, I figured it might be desirable for bloggers to keep visitors on a single blog post for longer using content pagination, with the caveat that consolidating a multi-part blog into a single multi-page blog will likely improve visit times but worsen bounce-rate.

As an interesting exercise I thought I would have a go at implementing a JavaScript library to paginate Blogger.com blog posts.

For the implementation, jQuery seemed like an obvious choice, recognising its popularity and as the incumbent technology for doing such things, least not because the work that inspired me was written using jQuery also.

NB: I am trying to publish this library as a Blogger gadget, but am yet to succeed - watch this space!

Quickstart


Structure you posts like so:
  1. Leading and header content
  2. Start a page and each subsequent page with <h2 class="pagebreak">Page Title</h2>
  3. End your paginated content with <h2 class="pagelistpagelinks"></h2>
  4. Finsih off with trailing and footer content
NB: leading and trailing content will be visible always, regardless of which page you are on.

Pre-Requisites and Installation

Make sure you have jQuery installed; as mentioned, I will try to bundle this as a gadget, but jQuery needs to be installed separately in your blog's template - Google will tell you how.

Install a UUID function with the name uuid into jQuery so the paginator can use it like $.uuid()
For your convience, you can use this UUID function adapted here for jQuery, lifted from Kevin Hakanson's answer on StackOverflow; edit the layout of you blog and add a 'HTML/JavaScript' gadget at the bottom with the following content:


To install the BlogPaginator code, again edit the layout of you blog and add a 'HTML/JavaScript' gadget at the bottom with the following content:



Credit Where Credit is Due


Firstly let me give a shout to Harshit Jain, whose work largely inspired and seeded mine.

I liked what I saw there but thought it was a bit too involved: let's say the blogger is your somewhat tech-savy, retired grandmother posting baking recipes; do we really want her taking time out from baking to fiddle around with jQuery? Hell nah! #wewantcake

Also, the pages are statically formed and numbered, so adding new ones or restructuring becomes a chore.

...now rinse and repeat for every blog post.

So I sought to make this more automatic with minimal first-time setup - in installing the library - and just imposing the need to write HTML.

The Approach


So I had two objectives initially:
  1. Allow bloggers to write new posts with pages added ad-hoc or worked into their document plan
  2. Allow bloggers to easily retro-fit long past posts or consolidate multi-part blog posts split instead across pages
It seemed intuitive to model a page as an item with content: old pre-existing blogs likely won't have such an obvious structure; while it is easy to plan a new post like this, you realise it isn't all that convenient when you start moving content and pages around - but we do not need to abandon this intuition just yet...

Having worked a lot with XML, in all forms including HTML, I know you basically have two ways to process a document:
  • With the DOM, which is built upfront and you use something like XPath to traverse and locate the elements you want
  • With a StAX parser, that processes a document tag (node) by tag, where start <div> and end </div> tags are two different events (if I had to guess, a DOM would be built this way)
The StAX idea is key here and, combined with document manipulation, allows us to separate the way content and pages are authored from how content and pages are rendered, that is, a structural transformation.

In other words, if you can drop in a 'bagebreak' marker that your processor can use to create a new page and swallow up all the content until the next pagebreak, implying the end of a page and the start of the next, then we are on our way to a solution.

This is easy, we just use a standard HTML tag; it can pretty much be anything, knowing we can replace it with something more useful and extract content - if it has any - and use it later.

For this I chose the h2 tag with a class value of pagebreak:
<h2 class="pagebreak">Page Title</h2>
The Page Title will be extracted and used to build a Table of Contents (ToC).

Using the <h2 /> tag this way feels a lot more natural and gets out the way of content authoring; you spend less effort thinking and implementing your pagination structure and more about what you want to write e.g. how she baked that cake!

Once all the content is authored with pagebreaks, we need another marker to indicate to the processor that there are no more pages and it needs to insert the click-able page navigation functionality. The same principles apply here, but we use a class value of pagelistpagelinks and note that any content is discarded:
<h2 class="pagelistpagelinks"></h2>

The Implementation Details


To implement this we don't actually use a StAX parser, we just simulate one using jQuery's .contents() method; it's important to use .contents() and not .children() as the former is one of few jQuery operations that process text-nodes, whereas the latter does not.

So when our pseudo-jQuery-StAX processor starts up, it creates a page for each pagebreak and some corresponding meta-data, until it sees a pagelistpagelinks; at this point it knows:
  1. Where the first page started
  2. How many pages there are
  3. The page title for each
  4. And where the last page ended, which is not necessarily the end of the blog post!
So we can generate the page navigation links after the last page, but we can also jump back and insert another set of page navigation links before the first page too; this is useful for long pages where, if the page is sufficiently introduced, the reader can decide early whether to keep reading or click ahead or back without needing to scroll to the links at the bottom of the paginated section.

Furthermore, with the page titles stored, we can jump back and insert a ToC, where the each page title links through to its page.

For usability, the implementation disables links to the page you are currently on and also provides 'Show All' links.

I have not (nor planned to) implement First, Previous, Next and Last semantics as I wouldn't expect a blog post to be that long - First and Last would be easy, Prev and Next a little less so.

And that's it... for a sunny day scenario at least.

What Happens When Multiple Posts Are Listed? Chaos!


The above all works fine when, say in a testing scenario, you are writing a web page and using the <body /> tag to demark content for pagination i.e. with a $("body") jQuery.

When in Blogger.com, pages must obey the rules like any other web-page, that is, the <body /> tag contains all the renderable content you see in the browser window, including all the Blogger.com chrome, navigation links, gadget content, adverts etc and when on you blog's landing page, all the (recent) posts listed too.

The effect, in theory, is you get cross-post pagination, in practice you get a mess and missing content.

There are two steps to counteract this:

First we must set apart different posts and demark pagination content by something other than the <body /> tag; after some inspection you'll see Blogger.com use a <div /> tag with a post-body class entry to contain each post i.e.
<div class="... post-body ..."></div>
We can grab this using a $("div.post-body") jQuery.

Secondly, we need to make page links unique to a post so we don't get cross-post page linking.

This is easily done by introducing a UUID and associating that with a post and all its corresponding page links.

That's it, sunny day and rainy scenarios accounted for.

As always, feedback and comments are welcome.

Also check back for progress updates on having this published as a Blogger.com gadget.

Wednesday, November 19, 2014

Darren on Flex: FlexUnit4 Testing with Parsley - Testing with Mock Injections

In Part-5 I showed how to tidy away all (most of) the Parsley Messaging and Flex event management boiler-plate by extending the Fluint-aware DSL introduced in Part-3, which made tests Parsley-aware.

This much overdue final part of the FlexUnit4 Testing with Parsley series demonstrates mock injection and leverages Mockito-Flex to achieve that.
(I will give a shout to the team behind Mockolate, as that is also a very good mocking library)

Mockito-Flex utilizes ASMock internally and I encountered a problem where the application-domain used by ASMock for creating mocks, differed from that used by Parsley for its managed context environment.
I managed to clone and patch the Mockito-Flex codebase (pull-request imminent) such that in this patched version, Mockito-Flex specifies to ASMock what application domain to use. Awesome!

The 'test' code re-re-re-re-revisted...

Mock Injection
Previously, a stubbed service implementation was used to provide the behaviour needed for the successful running of the tests.
The smell that comes with using stubs is that they tend to introduce test logic, as was the case here, which is:
  1. Only implicitly tested, by default of being used in a test and...
  2. Only ever used through test code and not main/business code, so does not really represent any business value
Furthermore, this test logic resides in a different class to the test making it harder to understand what is going on (or harder to debug it if/when something goes wrong).

We can rid ourselves of these code-smells by using mocking; the DSL provided by Mockito-Flex allows us to declaritively specify how the mocks in our Parsley context must behave AND we do that in-line with our tests.

With the mocking and Parsley-aware DSLs combined, we still get to write easy-to-read story-style tests i.e. given-when-then, like we did before.

DSL(Mocking + Parsley) - Inheritance = A New Approach
package com.darrenbishop.crm.directory.application {
    import com.darrenbishop.crm.directory.GetPersonCommandMockedComponentTestContext;
    import com.darrenbishop.crm.directory.domain.Person;
    import com.darrenbishop.support.create;
    import com.darrenbishop.support.flexunit.parsley.ParsleyDslRule;
    import com.darrenbishop.support.flexunit.parsley.dsl.*;

    import flash.events.ErrorEvent;

    import org.hamcrest.assertThat;
    import org.hamcrest.object.equalTo;
    import org.mockito.integrations.flexunit4.MockitoRule;
    import org.mockito.integrations.given;

    public class GetPersonCommandMockedParsleyRuleDSLComponentTest {

        [Rule(order=1)]
        public var mockito:MockitoRule = new MockitoRule();
        
        [Rule(order=2)]
        public var parsley:ParsleyDslRule = new ParsleyDslRule(GetPersonCommandMockedComponentTestContext);
        
        [Mock]
        public var service:DirectoryService;
        
        [Inject]
        public var command:GetPersonCommand;
        
        public var dodgyPerson:Person;
        
        public var soundPerson:Person;
        
        [Before]
        public function prepareEntities():void {
            dodgyPerson = create(Person, {'id': 1, 'firstname': 'John001', 'lastname': 'Smith001', 'phone': 6803225});
            soundPerson = create(Person, {'id': 2, 'firstname': 'John002', 'lastname': 'Smith002', 'phone': 6809168});
        }
        
        [Test(async,description='Test GetPersonCommand result-handler does not mangle the person found.')]
        public function resultDoesNotManglePersonFound():void {
            given(service.lookupById(soundPerson.id)).will(returnEventually(soundPerson));

            dispatchMessage(PersonEvent.newLookup(soundPerson.id));
            
            waitForMessage(PersonEvent.FOUND);
            then(function(event:PersonEvent, data:*):void {
                assertThat(event.type, equalTo('PersonEvent.found'));
                assertThat(event.person.fullname, equalTo('John002 Smith002'));
            });
        }

        [Test(async,description='Test GetPersonCommand result-handler verifies the id of the person found.')]
        public function resultVerifiesPersonFound():void {
            given(service.lookupById(dodgyPerson.id)).will(returnEventually(soundPerson));

            dispatchMessage(PersonEvent.newLookup(dodgyPerson.id));
            
            waitForError(ErrorEvent.ERROR);
            then(function(event:ErrorEvent, data:*):void {
                assertThat(event.text, equalTo(fmt('Found person (%d) does not match lookup person (%d)', soundPerson.id, dodgyPerson.id)));
            });
        }
    }
}

The first thing to notice is the test-case no-longer needs to inherit from the ParsleyHelper class; all that DSL goodness is made available in standalone functions, in much the same way as those provided in the org.hamcrest.*, org.mockito.integrations.* packages and Flex' top-level package.

Swapping out ParsleyRule and using ParsleyDslRule instead activates this non-inheritance approach; under-the-hood it ensures that each test will run in isolation and that any invoked Parsley-aware DSL-function will use the same singletons/managed-objects for that test e.g. the same [MessageDispatcher] or EventDispatcher.

Some test developers use inheritance to implement a suite of similar tests - given Flex only supports single-inheritance - it is nice to have the inheritance-chain freed-up to allow them to continue to do so.

That's all there really is to it!

The change to Mockito-Flex that allows us to specify the application domain is included below, along with the two additional classes that are needed to make the mock-injection work:

--- mockito-flex/mockito/src/main/flex/org/mockito/integrations/flexunit4/MockitoRule.as (revision 87:8a8720f988e55bc8daf60144d8d73e63a8cc69b7)
+++ mockito-flex/mockito/src/main/flex/org/mockito/integrations/flexunit4/MockitoRule.as (revision 87+:8a8720f988e5+)
@@ -10,6 +10,7 @@
 import org.flexunit.runners.model.FrameworkMethod;
 import org.flexunit.token.AsyncTestToken;
 import org.mockito.Mockito;
+import org.mockito.impl.AsmockADMockeryProvider;
 import org.mockito.integrations.currentMockito;
 
 public class MockitoRule extends MethodRuleBase implements IMethodRule
@@ -19,7 +20,7 @@
         super();
     }
 
-    private function classFor(test:Object):Class
+    protected function classFor(test:Object):Class
     {
         return Class(getDefinitionByName(getQualifiedClassName(test)));
     }
@@ -27,7 +28,7 @@
     override public function apply(base:IAsyncStatement, method:FrameworkMethod, test:Object):IAsyncStatement
     {
         var sequencer:StatementSequencer = new StatementSequencer();
-        currentMockito = new Mockito();
+        currentMockito = new Mockito(AsmockADMockeryProvider);
         sequencer.addStep(withMocksPreparation(classFor(test)));
         sequencer.addStep(withMocksAssignment(classFor(test), test));
         sequencer.addStep(base);

package org.mockito.impl
{
    import org.mockito.api.MockCreator;
    import org.mockito.api.MockInterceptor;
    import org.mockito.api.MockeryProvider;
    import org.mockito.api.SequenceNumberGenerator;
    import org.mockito.api.SequenceNumberTracker;

    /**
     *
     * Implementation of the mockery provider that creates asmock based implementation
     */
    public class AsmockADMockeryProvider implements MockeryProvider
    {
        private var mockInterceptor:MockInterceptor;

        private var mockCreator:AsmockADMockery;

        /**
         * Creates mockery provider
         */
        public function AsmockADMockeryProvider(sequenceNumberGenerator:SequenceNumberGenerator, sequenceNumberTracker:SequenceNumberTracker)
        {
            mockInterceptor = new MockInterceptorImpl(sequenceNumberTracker);
            mockCreator = new AsmockADMockery(mockInterceptor, sequenceNumberGenerator);
        }

        /**
         * Returns MockCreator
         * @return implementation of MockCreator
         */
        public function getMockCreator():MockCreator
        {
            return mockCreator;
        }

        /**
         * Returns MockInterceptor
         * @return implementation of MockInterceptor
         *
         */
        public function getMockInterceptor():MockInterceptor
        {
            return mockInterceptor;
        }
    }
}

package org.mockito.impl
{
    import asmock.framework.MockRepository;
    import asmock.framework.asmock_internal;

    import flash.events.ErrorEvent;
    import flash.events.Event;
    import flash.events.IEventDispatcher;
    import flash.system.ApplicationDomain;
    import flash.utils.Dictionary;

    import org.flemit.reflection.MethodInfo;
    import org.flemit.reflection.Type;
    import org.floxy.IInvocation;
    import org.mockito.api.Invocation;
    import org.mockito.api.MockCreator;
    import org.mockito.api.MockInterceptor;
    import org.mockito.api.SequenceNumberGenerator;

    use namespace asmock_internal;

    /**
     * Asmock bridge. Utilizes asmock facilities to create mock objects.
     * @private
     */
    public class AsmockADMockery extends MockRepository implements MockCreator
    {
        public var interceptor:MockInterceptor;

        protected var _names:Dictionary = new Dictionary();

        private var sequenceNumberGenerator:SequenceNumberGenerator;

        public function AsmockADMockery(interceptor:MockInterceptor, sequenceNumberGenerator:SequenceNumberGenerator)
        {
            super(new ADProxyRepository(ApplicationDomain.currentDomain));
            this.interceptor = interceptor;
            this.sequenceNumberGenerator = sequenceNumberGenerator;
        }

        /**
         * A factory method that creates Invocation out of asmock invocation
         * @param invocation asmock invocation object
         * @return mockito invocation
         *
         */
        public function createFrom(invocation:IInvocation):Invocation
        {
            var niceMethodName:String = new AsmockMethodNameFormatter().extractFunctionName(invocation.method.fullName);
            return new InvocationImpl(invocation.invocationTarget,
                    invocation.method.fullName,
                    invocation.arguments,
                    new AsmockOriginalCallSeam(invocation),
                    sequenceNumberGenerator.next());
        }

        public function prepareClasses(classes:Array, calledWhenClassesReady:Function, calledWhenPreparingClassesFailed:Function = null):void
        {
            var dispatcher:IEventDispatcher = super.prepare(classes);
            var repositoryPreparedHandler:Function = function (e:Event):void
            {
                calledWhenClassesReady();
            };
            
            var repositoryPreparationFailed:Function = function (e:Event):void
            {
                if (calledWhenPreparingClassesFailed != null)
                    calledWhenPreparingClassesFailed();
            };
            dispatcher.addEventListener(Event.COMPLETE, repositoryPreparedHandler);
            dispatcher.addEventListener(ErrorEvent.ERROR, repositoryPreparationFailed);
        }

        public function mock(clazz:Class, name:String = null, constructorArgs:Array = null):*
        {
            if (name == null)
            {
                name = Type.getType(clazz).name;
            }
            var mock:Object = createStrict(clazz, constructorArgs);
            registerAlias(mock, name);
            return mock;
        }

        override asmock_internal function methodCall(invocation:IInvocation, target:Object, method:MethodInfo, arguments:Array):*
        {
            return interceptor.methodCalled(createFrom(invocation));
        }

        /**
         *
         * @param mock
         * @param name
         */
        public function registerAlias(mock:Object, name:String):void
        {
            _names[mock] = name;
        }
    }
}

Epilogue


Although I doubt anyone has been waiting, apologies for taking so long to wrap this all up.
All the same, it was an interesting exercise to figure all this out.

Ironically, I likely will not be engaging in any Flex development going forward, as I have recently turned my attention to iOS and SCALA.
However I will commit to getting the Mockito-Flex changes pushed to my fork on BitBucket and raise a pull request with Loomis, the author. DONE!

Thanks for reading and comments are welcome as always.

Thursday, June 16, 2011

Darren on Flex: FlexUnit4 Testing with Parsley - Testing with a Parsley-Aware DSL

In Part-4 I showed how to use [RunWith] and [Rule] to locate and hide Parsley context initialization; with the reduced duplication in this approach tests are left to focus on what is important - testing.

In Part-5, I'll show how to reduce the noise hide the complexities of Parsley Messaging, used to implement decoupling between components, by extending the Fluint-aware DSL introduced in Part-3 to be Parsley-aware.

The 'test' code re-re-re-revisted...

Hiding Messages
As mentioned, this improved DSL attempts to hide uses of the Parsley Framework. The approach is limited to hiding usage of the Parsley Messaging API, but supports a comfortable balance of declarative and imperative coding seen in story-style testing i.e. given-when-then.

We retain the declarative approach to dependency injection i.e. with [Inject], yet this approach is less fitting for messaging/coupling management in a test(-method). Story tests tend to read as a sequence of imperative commands to prepare (Given), actuate (When) and inspect (Then) the object-under-test. In this style you often specify which message to dispatch and which to listen out for... and when... and for how long (timeout). You have the opportunity to state your messaging intentions clearly, in-line, that is, not having a test distributed over several methods (some of which being annotated with [MessageHandler(...)] metadata tags).

package com.darrenbishop.crm.directory.application {
    import com.darrenbishop.crm.directory.GetPersonCommandComponentTestContext;
    import com.darrenbishop.support.flexunit.parsley.ParsleyHelper;
    
    import org.flexunit.asserts.fail;
    import flash.events.ErrorEvent;
    import org.flexunit.assertThat;
    import org.hamcrest.object.equalTo;
    import com.darrenbishop.support.create;
    import com.darrenbishop.crm.directory.domain.Person;
    import com.darrenbishop.support.flexunit.parsley.ParsleyRule;
    
    public class GetPersonCommandParsleyRuleDSLComponentTest extends ParsleyHelper {
        [Rule]
        public var rule:ParsleyRule = new ParsleyRule(GetPersonCommandComponentTestContext);
        
        [Inject]
        public var service:StubDirectoryService;
        
        [Inject]
        public var command:GetPersonCommand;
        
        public var dodgyPerson:Person;
        
        public var soundPerson:Person;
        
        [Before]
        public function primeService():void {
            dodgyPerson = create(Person, {'id': 1, 'firstname': 'John001', 'lastname': 'Smith001', 'phone': 6803225});
            soundPerson = create(Person, {'id': 2, 'firstname': 'John002', 'lastname': 'Smith002', 'phone': 6809168});
            
            service.add(dodgyPerson, soundPerson);
            
            service.dodgyPerson = dodgyPerson.id;
            service.soundPerson = soundPerson.id;
        }
        
        [Test(async,description='Test GetPersonCommand result-handler does not mangle the person found.')]
        public function resultDoesNotManglePersonFound():void {
            dispatchMessage(PersonEvent.newLookup(soundPerson.id));
            waitForMessage(PersonEvent.FOUND, 1000);
            thenAssert(function(event:PersonEvent, data:*):void {
                assertThat(event.type, equalTo('PersonEvent.found'));
                assertThat(event.person.fullname, equalTo('John002 Smith002'));
            });
        }
        
        [Test(async,description='Test GetPersonCommand result-handler verifies the id of the person found.')]
        public function resultVerifiesPersonFound():void {
            dispatchMessage(PersonEvent.newLookup(dodgyPerson.id));
            waitForMessage(ErrorEvent.ERROR, 1000);
            thenAssert(function(event:ErrorEvent, data:*):void {
                assertThat(event.text, equalTo(sprintf('Found person (%d) does not match lookup person (%d)', soundPerson.id, dodgyPerson.id)));
            });
        }
    }
}
Note the test class now extends ParsleyHelper, building on the inheritance approach to provide access to the messaging-DSL methods; you'll see shortly that this new helper class extends from AsyncHelper, so the async-DSL methods are still available.

There are a number of changes to note and to make them clear I've provided a diff generated from the test above and that presented in Part-4:

--- C:/Dev/workspaces/flex/parsley-flexunit/src/test/flex/com/darrenbishop/crm/directory/application/GetPersonCommandParsleyRuleComponentTest.as Wed Jun 15 21:00:39 2011
+++ C:/Dev/workspaces/flex/parsley-flexunit/src/test/flex/com/darrenbishop/crm/directory/application/GetPersonCommandParsleyRuleDSLComponentTest.as Wed Jun 15 20:54:17 2011
@@ -4,3 +4,3 @@
     import com.darrenbishop.support.create;
-    import com.darrenbishop.support.flexunit.async.AsyncHelper;
+    import com.darrenbishop.support.flexunit.parsley.ParsleyHelper;
     import com.darrenbishop.support.flexunit.parsley.ParsleyRule;
@@ -8,3 +8,2 @@
     import flash.events.ErrorEvent;
-    import flash.events.EventDispatcher;
     
@@ -12,5 +11,4 @@
     import org.hamcrest.object.equalTo;
-    import org.spicefactory.parsley.core.messaging.MessageProcessor;
     
-    public class GetPersonCommandParsleyRuleComponentTest extends AsyncHelper {
+    public class GetPersonCommandParsleyRuleDSLComponentTest extends ParsleyHelper {
         [Rule]
@@ -18,5 +16,2 @@
         
-        [MessageDispatcher]
-        public var dispatcher:Function;
-        
         [Inject]
@@ -31,8 +26,4 @@
         
-        private var eventDispatcher:EventDispatcher;
-        
         [Before]
         public function primeService():void {
-            eventDispatcher = new EventDispatcher();
-            
             dodgyPerson = create(Person, {'id': 1, 'firstname': 'John001', 'lastname': 'Smith001', 'phone': 6803225});
@@ -46,16 +37,6 @@
         
-        [MessageError(type='com.darrenbishop.crm.directory.application.PersonEvent')]
-        public function rethrowIt(processor:MessageProcessor, error:Error):void { 
-            eventDispatcher.dispatchEvent(toEvent(error));
-        }
-        
-        [MessageHandler(selector='PersonEvent.found')]
-        public function passItOn(event:PersonEvent):void {
-            eventDispatcher.dispatchEvent(event);
-        }
-        
         [Test(async,description='Test GetPersonCommand result-handler does not mangle the person found.')]
         public function resultDoesNotManglePersonFound():void {
-            dispatcher(PersonEvent.newLookup(soundPerson.id));
-            waitFor(eventDispatcher, PersonEvent.FOUND, 1000);
+            dispatchMessage(PersonEvent.newLookup(soundPerson.id));
+            waitForMessage(PersonEvent.FOUND, 1000);
             thenAssert(function(event:PersonEvent, data:*):void {
@@ -68,4 +49,4 @@
         public function resultVerifiesPersonFound():void {
-            dispatcher(PersonEvent.newLookup(dodgyPerson.id));
-            waitFor(eventDispatcher, ErrorEvent.ERROR, 1000);
+            dispatchMessage(PersonEvent.newLookup(dodgyPerson.id));
+            waitForMessage(ErrorEvent.ERROR, 1000);
             thenAssert(function(event:ErrorEvent, data:*):void {
Counting the new lines (6) and the dropped lines (20, not including blank-lines) reveals a net 14 line reduction of boilerplate code that would otherwise be repeated as your tests grow in quantity and size.

With this improved DSL, tests become even simpler to read.

[MessageDispatcher] - refactored
As mentioned all the explicit Parsley Messaging Framework usage has been pulled up to the ParsleyHelper super class:
package com.darrenbishop.support.flexunit.parsley {
    import com.darrenbishop.support.flexunit.async.AsyncHelper;
    
    import flash.events.Event;
    import flash.events.EventDispatcher;
    
    import org.spicefactory.parsley.core.messaging.MessageProcessor;

    public class ParsleyHelper extends AsyncHelper {
        [MessageDispatcher]
        public var dispatcher:Function;
        
        protected var eventDispatcher:EventDispatcher;
        
        [Before]
        public function prepareEventDispatcher():void {
            eventDispatcher = new EventDispatcher();
        }
        
        [MessageError]
        public function rethrowIt(processor:MessageProcessor, error:Error):void { 
            eventDispatcher.dispatchEvent(toEvent(error));
        }
        
        [MessageHandler]
        public function passItOn(msg:Event):Boolean {
            return eventDispatcher.dispatchEvent(msg);
        }
        
        protected function dispatchEvent(event:Event):void {
            eventDispatcher.dispatchEvent(event);
        }
        
        protected function dispatchMessage(event:Event):void {
            dispatcher(event);
        }
        
        protected function dispatchError(error:Error):void {
            eventDispatcher.dispatchEvent(toEvent(error));
        }
        
        protected function waitForMessage(eventType:String, timeout:Number=1000):void {
            waitFor(eventDispatcher, eventType, timeout);
        }
        
        protected function waitForError(eventType:String, timeout:Number=1000):void {
            waitForMessage(eventType, timeout);
        }
    }
}
Here we have all the methods pertinent to Parsley messaging, laid out and self explanatory.

Furthermore this approach does a good job of hiding usage of the Flex Event mechanism; this messaging-DSL removes the need to interact explicitly with an EventDispatcher.

What's Next...

Part 6: All That, But With Mocking
So I've got one more Ace up my sleeve - mock-injection. At this point I'm not even sure this is a good idea or whether there's a place for this technique in any practical testing scenario. I have recently read the Spring documentation on this and have since seen this done in enough places to be convinced there is value in it for component/sub-system testing.

Nonetheless, I figured it out and implemented it; the implementation in fact requires some modifications, including some to Mockito-Flex classes. I've contributed these code changes to the Mockito-Flex project, which I believe will be rolled in or otherwise accommodated soon; you can read more about it here

Wednesday, April 20, 2011

Darren on Flex: FlexUnit4 Testing with Parsley - Improved Parsley Support with FlexUnit's [RunWith(...)] & [Rule]

In Part-3 I showed how a DSL can be used to reduce the complexity of asynchronous testing when using the Fluint Sequence API. With this DSL I was also able to remove several lines of boilerplate code. These might be modest improvements, but the introduction of a DSL paves the way for more concise tests.

In Part-4, I'll show how to integrate Parsley into FlexUnit by using the [RunWith] and [Rule] hook mechanisms to make FlexUnit do the heavy lifting i.e. context initialization and dependency injection.

The 'test' code re-re-revisted...

As mentioned there are two approaches, [RunWith] and [Rule]. I had previously held-back from exploring the [Rule] option as it comes with FlexUnit 4.1, which up until very recently, had only been available in beta. I explore this second option later in this post, but first...
The [RunWith] approach
package com.darrenbishop.crm.directory.application {
    import com.darrenbishop.crm.directory.GetPersonCommandComponentTestContext;GetPersonCommandComponentTestContext;
    import com.darrenbishop.support.flexunit.parsley.ParsleyRunner;ParsleyRunner;
    
    import org.flexunit.asserts.fail;
    import flash.events.ErrorEvent;
    import org.flexunit.assertThat;
    import org.hamcrest.object.equalTo;
    import com.darrenbishop.support.create;
    import com.darrenbishop.crm.directory.domain.Person;
    import com.darrenbishop.support.flexunit.async.AsyncHelper;
    import org.spicefactory.parsley.core.context.Context;
    import flash.events.EventDispatcher;
    import org.spicefactory.parsley.core.messaging.MessageProcessor;
    
    [RunWith('com.darrenbishop.support.flexunit.parsley.ParsleyRunner')]
    [Context('com.darrenbishop.crm.directory.GetPersonCommandComponentTestContext')]
    public class GetPersonCommandParsleyRunnerComponentTest extends AsyncHelper {
        [MessageDispatcher]
        public var dispatcher:Function;
        
        [Inject]
        public var context:Context;
        
        [Inject]
        public var service:StubDirectoryService;
        
        [Inject]
        public var command:GetPersonCommand;
        
        public var dodgyPerson:Person;
        
        public var soundPerson:Person;
        
        private var eventDispatcher:EventDispatcher;
        
        [Before]
        public function primeService():void {
            eventDispatcher = new EventDispatcher();
            
            dodgyPerson = create(Person, {'id': 1, 'firstname': 'John001', 'lastname': 'Smith001', 'phone': 6803225});
            soundPerson = create(Person, {'id': 2, 'firstname': 'John002', 'lastname': 'Smith002', 'phone': 6809168});
            
            service.add(dodgyPerson, soundPerson);
            
            service.dodgyPerson = dodgyPerson.id;
            service.soundPerson = soundPerson.id;
        }
        
        [MessageError(type='com.darrenbishop.crm.directory.application.PersonEvent')]
        public function rethrowIt(processor:MessageProcessor, error:Error):void { 
            eventDispatcher.dispatchEvent(toEvent(error));
        }
        
        [MessageHandler(selector='PersonEvent.found')]
        public function passItOn(event:PersonEvent):void {
            eventDispatcher.dispatchEvent(event);
        }
        
        [Test(async,description='Test GetPersonCommand result-handler does not mangle the person found.')]
        public function resultDoesNotManglePersonFound():void {
            dispatcher(PersonEvent.newLookup(soundPerson.id));
            waitFor(eventDispatcher, PersonEvent.FOUND, 1000);
            thenAssert(function(event:PersonEvent, data:*):void {
                assertThat(event.type, equalTo('PersonEvent.found'));
                assertThat(event.person.fullname, equalTo('John002 Smith002'));
            });
        }
        
        [Test(async,description='Test GetPersonCommand result-handler verifies the id of the person found.')]
        public function resultVerifiesPersonFound():void {
            dispatcher(PersonEvent.newLookup(dodgyPerson.id));
            waitFor(eventDispatcher, ErrorEvent.ERROR, 1000);
            thenAssert(function(event:ErrorEvent, data:*):void {
                assertThat(event.text, equalTo(sprintf('Found person (%d) does not match lookup person (%d)', soundPerson.id, dodgyPerson.id)));
            });
        }
    }
}
I declare the ParsleyRunner class as the default attribute to the [RunWith] metadata tag; I import and reference the same (at the top of the excerpt) to ensure the runner is linked in. This highlights one of the fundamental problems with this approach: you must repeat you intention too many times - once should be enough.

The same goes for the GetPersonCommandComponentTestContext; the runner needs to be told somehow which Parsley context to initialize. Perhaps there are better ways to communicate to the runner which context to use, with static members maybe, but the problem persists for the runner itself so there's little value in exploring such an enhancement.

The only other significant change is the [Before] annotated method; this method is no-longer responsible for building the Parsley context so I renamed it from initializeContext() to primeService(), as that's all it now does; it primes the StubDirectoryService with people and the id to trigger the error case.

Introducing the the ParsleyRunner...
package com.darrenbishop.support.flexunit.parsley {
    import flash.utils.getDefinitionByName;
    import flash.utils.getQualifiedClassName;
    
    import flex.lang.reflect.metadata.MetaDataAnnotation;
    
    import org.flexunit.internals.runners.statements.IAsyncStatement;
    import org.flexunit.internals.runners.statements.StatementSequencer;
    import org.flexunit.runner.notification.IRunNotifier;
    import org.flexunit.runners.BlockFlexUnit4ClassRunner;
    import org.flexunit.runners.model.FrameworkMethod;

    public class ParsleyRunner extends BlockFlexUnit4ClassRunner {
        public static const CONTEXT_METADATA_NAME:String = 'Context';
        
        private var contextDescriptor:Class;
        
        public function ParsleyRunner(cls:Class) {
            super(cls);
            var ctxMetaData:MetaDataAnnotation = testClass.klassInfo.getMetaData(CONTEXT_METADATA_NAME);
            this.contextDescriptor = classFor(ctxMetaData.defaultArgument.key)
        }
        
        private function classFor(name:String):Class {
            return Class(getDefinitionByName(getQualifiedClassName(name)));
        }
        
        private function withParsleyContextBuilt(test:Object):IAsyncStatement {
            return new BuildParsleyContext(test, contextDescriptor);
        }

        protected override function withBefores(method:FrameworkMethod, test:Object, statement:IAsyncStatement):IAsyncStatement {
            if (contextDescriptor) {
                var sequencer:StatementSequencer = new StatementSequencer();
                sequencer.addStep(withParsleyContextBuilt(test));
                sequencer.addStep(super.withBefores(method, test, statement));
                return sequencer;
            }
            else {
                return super.withBefores(method, test, statement);
            }
        }
    }
}
I determine the class that describes the Parsley context for this test in the constructor, by retrieving the default attribute value of the [Context] metadata tag; this I consider to be a one-off class-level operation. The withBefores(...) template method is invoked before each test method, to contribute to the preparation of the environment in which the test method will execute; this method delegates to withParsleyContextBuilt(...) to generate a BuildParsleyContext command-object. BuildParsleyContext is not a Parsley command, as in the one being tested - it's just the pattern/convention used in the FlexUnit internals.
BuildParsleyContext, the heavy lifter
This command-object does all the work using the Parsley ActionScript3 API for context initialization:
package com.darrenbishop.support.flexunit.parsley {
    import flash.utils.getDefinitionByName;
    
    import org.flexunit.internals.runners.statements.AsyncStatementBase;
    import org.flexunit.internals.runners.statements.IAsyncStatement;
    import org.flexunit.token.AsyncTestToken;
    import org.spicefactory.parsley.core.context.Context;
    import org.spicefactory.parsley.flex.FlexContextBuilder;

    public class BuildParsleyContext extends AsyncStatementBase implements IAsyncStatement {
        protected var test:Object;
        protected var contextDescriptor:Class;
        
        public function BuildParsleyContext(target:Object, contextDescriptor:Class) {
            this.test = target;
            this.contextDescriptor = contextDescriptor;
        }
        
        public function evaluate(parentToken:AsyncTestToken):void {
            buildContext(parentToken);
        }

        private function buildContext(parentToken:AsyncTestToken):void {
            var error:Error = null;
            try {
                var ctx:Context = FlexContextBuilder.build(contextDescriptor);
                ctx.createDynamicContext().addObject(test);
            }
            catch (e:Error) {
                error = e;
            }
            
            parentToken.sendResult(error);
        }
    }
}
Basically, what once lived and would have been replicated in the [Before] methods of each and every Parsley-powered test, now lives here; but again, there's nothing new, just a relocation of code to somewhere more appropriate for re-use.

And that's it for the [RunWith] approach, but now with the relase of FlexUnit-4.1, we have...

The [Rule] approach
This hook mechanism completely solves the problem of having to declare the runner implementation class as a string in a metadata attribute:
package com.darrenbishop.crm.directory.application {
    import com.darrenbishop.crm.directory.GetPersonCommandComponentTestContext;
    import com.darrenbishop.crm.directory.domain.Person;
    import com.darrenbishop.support.create;
    import com.darrenbishop.support.flexunit.async.AsyncHelper;
    import com.darrenbishop.support.flexunit.parsley.ParsleyRule;
    
    import flash.events.ErrorEvent;
    import flash.events.EventDispatcher;
    
    import org.flexunit.assertThat;
    import org.hamcrest.object.equalTo;
    import org.spicefactory.parsley.core.messaging.MessageProcessor;
    
    public class GetPersonCommandParsleyRuleComponentTest extends AsyncHelper {
        [Rule]
        public var rule:ParsleyRule = new ParsleyRule(GetPersonCommandComponentTestContext);
        
        [MessageDispatcher]
        public var dispatcher:Function;
        
        [Inject]
        public var service:StubDirectoryService;
        
        [Inject]
        public var command:GetPersonCommand;
        
        public var dodgyPerson:Person;
        
        public var soundPerson:Person;
        
        private var eventDispatcher:EventDispatcher;
        
        [Before]
        public function primeService():void {
            eventDispatcher = new EventDispatcher();
            
            dodgyPerson = create(Person, {'id': 1, 'firstname': 'John001', 'lastname': 'Smith001', 'phone': 6803225});
            soundPerson = create(Person, {'id': 2, 'firstname': 'John002', 'lastname': 'Smith002', 'phone': 6809168});
            
            service.add(dodgyPerson, soundPerson);
            
            service.dodgyPerson = dodgyPerson.id;
            service.soundPerson = soundPerson.id;
        }
        
        [MessageError(type='com.darrenbishop.crm.directory.application.PersonEvent')]
        public function rethrowIt(processor:MessageProcessor, error:Error):void { 
            eventDispatcher.dispatchEvent(toEvent(error));
        }
        
        [MessageHandler(selector='PersonEvent.found')]
        public function passItOn(event:PersonEvent):void {
            eventDispatcher.dispatchEvent(event);
        }
        
        [Test(async,description='Test GetPersonCommand result-handler does not mangle the person found.')]
        public function resultDoesNotManglePersonFound():void {
            dispatcher(PersonEvent.newLookup(soundPerson.id));
            waitFor(eventDispatcher, PersonEvent.FOUND, 1000);
            thenAssert(function(event:PersonEvent, data:*):void {
                assertThat(event.type, equalTo('PersonEvent.found'));
                assertThat(event.person.fullname, equalTo('John002 Smith002'));
            });
        }
        
        [Test(async,description='Test GetPersonCommand result-handler verifies the id of the person found.')]
        public function resultVerifiesPersonFound():void {
            dispatcher(PersonEvent.newLookup(dodgyPerson.id));
            waitFor(eventDispatcher, ErrorEvent.ERROR, 1000);
            thenAssert(function(event:ErrorEvent, data:*):void {
                assertThat(event.text, equalTo(sprintf('Found person (%d) does not match lookup person (%d)', soundPerson.id, dodgyPerson.id)));
            });
        }
    }
}
The shift can be simply thought of as declaring the runner implementation as a member variable i.e. rule and annotating it with the [Rule] metadata tag, rather than as a string metadata attribute. Of course, now it's no longer a runner, but a rule and extends a different parent class and implements slightly different template methods... but for the most part it's the same.
The ParsleyRule to rule it all
As mentioned there are few differences, but one welcome difference, now that the rule is declared and initialized as an instance variable, is that in doing so the constructor is called and any arbitrary arguments can be passed in. I use this to communicate which Parsley context to initialize, by passing in the class that defines it.
package com.darrenbishop.support.flexunit.parsley {
    import org.flexunit.internals.runners.statements.IAsyncStatement;
    import org.flexunit.internals.runners.statements.MethodRuleBase;
    import org.flexunit.internals.runners.statements.StatementSequencer;
    import org.flexunit.rules.IMethodRule;
    import org.flexunit.runners.model.FrameworkMethod;
    import org.flexunit.token.AsyncTestToken;

    public class ParsleyRule extends MethodRuleBase implements IMethodRule {
        private var contextDescriptor:Class;
        
        public function ParsleyRule(contextDescriptor:Class) {
            super();
            this.contextDescriptor = contextDescriptor;
        }
        
        override public function apply(base:IAsyncStatement, method:FrameworkMethod, test:Object):IAsyncStatement {
            var sequencer:StatementSequencer = new StatementSequencer();
            sequencer.addStep(withParsleyContextBuilt(test));
            sequencer.addStep(base);
            return super.apply(sequencer, method, test);
        }
        
        private function withParsleyContextBuilt(test:Object):IAsyncStatement {
            return new BuildParsleyContext(test, contextDescriptor);
        }
        
        override public function evaluate(parentToken:AsyncTestToken):void {
            super.evaluate(parentToken);
            proceedToNextStatement();
        }
    }
}
The [Rule] approach has the benefit that it does not exhaust the use of inheritance, nor does it use [RunWith], both of which are use-once mechanisms.

There is now the benefit that multiple rules can be defined and used in conjunction with each other; this removes the impediments to mocking described in Part-1

I have actually succeeded in mocking a DirectoryService instance and embedding that instance into the Parsley context ready for dependency-injection, but that's another blog :-)

What's Next...

Part 5: Testing with a Parsley-Aware DSL
The final (planned) part of this blog series will demonstrate the ParsleyHelper base class. ParsleyHelper extends from AsyncHelper, introduced in Part-3, to add a layer of abstraction for all the Parsley bits and pieces; this improved DSL implementation allows for the removal of all reference to anything-Parsley

... except for the ParsleyRule

... and the ParsleyHelper.