Stubbing a Command Dependency With Mockolate and FlexUnit

In Test Driven Development (TDD) and Unit Testing, it is often necessary to provide the Class Under Test (CUT) with a stub of a class for which it has a dependency. For instance, this example illustrates a command class that injects a model. In order to run a test against the execute method of the CUT we need to ensure that the model and related model properties exist for the CUT in order to assert against the command’s execute method.
Mocks and Stubs are Different
First, I want to describe the difference between a Mock and a Stub as there seems to be general confusion over the slight difference that exists. According to Roy Osherove, in “The Art of Unit Testing” a Stub is defined as:

A stub is a controllable replacement for an existing dependency (or collaborator) in the system.

And a Mock is defined as:

A mock object is a fake object in the system that decides whether the unit test has passed or failed. It does so by verifying whether the object under test interacted as expected with the fake object.

The difference between a Mock and a Stub isn’t necessarily evident in simply looking at the test code, the two may look very similar. Instead, it is necessary to consider just what it is that a Mock does as opposed to a Stub. The difference can be found in how each one is used. Quite simply, a Mock gets asserted against, we are testing it to verify that the CUT interacted with the Mock as expected; a Stub is not under test and is provided simply as a means to fulfill a dependency of the CUT. So, again, a Mock is under test and a Stub is a helper class that is fulfilling a dependency of the CUT and it, itself, is not under test.

Here is a diagram that illustrates a model Stub (fake) as is used in a test that asserts against a class, a command for our purposes, for which has a dependency on the model. Notice the layer of abstraction that is created by the use of an Interface which allows us to swap the the Stub in place of the actual model class by injecting the StubModel rather than Model as would be used in production code:
Stubbing A Model Dependency
Mockolate facilitates the injection of a “Mockolate” for us using some metadata to prepare and inject our Stub dependency. There are a couple of Mockolate helpers that are important to take note of as I will be using them in the example which follows. In FlexUnit there is the concept of a rule. Like [Before] and [After] provide that a method will be run before or, respectively, after each test, we can create a rule that defines a dependency injection and have it inject the additional functionality into our test. Mockolate’s [Rule] metadata is a helper that invokes FlexUnit’s [Rule] for us, thereby simplifying the implementation of injected dependency. Using MockolateRule will asynchronously prepare your dependency before each test and will wait for prepare completion prior to running each test. MockolateRule prepares the dependency prior to needing it, ensuring that it exists when used.
Then how do we get our dependency prepared? Mockolate has another metadata tag, [Mock]. Any public instance variable declared with [Mock] metadata will be automatically prepared and injected for us. This is very powerful and very sweet!!
So how do you use this stuff?
Let’s look at some code to help illustrate how we implement Mockolate Rule and Mockolate Mock and setup our test class:

public class MyCommandTest
{
	[Rule]
	public var rule:MockolateRule = new MockolateRule();

	[Mock]
	public var model:IModelInterface;

	private var instanceCommand:MyCommand;
	protected static const MODEL_OBJECT:ModelObject = new ModelObject();

	[Before]
	public function setUp():void
	{
		instanceCommand = new MyCommand();
		instanceCommand.eventDispatcher = new EventDispatcher();
		instanceCommand.event = new MyEvent ( MyEvent.DO_SOMETHING, false, false, MODEL_OBJECT );
		instanceCommand.model = model;
	}

	[After]
	public function tearDown():void
	{
		instanceCommand = null;
	}
}

In the MyCommand test class the following Mockolate and declarations are getting defined:

  • Create a new Mockolate Rule
  • Create a new Mockolate Mock of the model to be prepared and injected
  • Create an instand of the command CUT
  • Create a constant of the model object which is the dependency property we need

We need to write our setup and teardown methods which will run before and after each test:

  • Using FlexUnit [Before], create setup which will run before each test in the class
  • Create a new instanceCommand
  • Create a new EventDispatcher as our Robotlegs Command needs it
  • Create a new event as our command happens to inject this event
  • Assign the model that Mockolate will have prepared for us
  • Using FlexUnit [After], create a teardown method to clear our setup before the next test

At this point we are ready to write our first test. This test will check to see if the overridden public method execute actually does what it is supposed to. The execute method in this command updates the injected model with an object payload from the injected event. Although we need to test that the model does get updated, we are not testing the model here, we only need it because it is a dependency of the command, which we are testing to see that it successfully updates the model.

[Test]
public function testInstanceUpdatesModel_updatesModel_instanceCommandUpdatesModel():void
{
        stub(instanceCommand.model).getter("modelObject").returns(MODEL_OBJECT);
	instanceCommand.execute();
}

A bit of convention explained here. The test name provides for three distinct pieces of information that will be valuable to yourself and anyone who later is maintaining your tests. A test class name provides the following information:

  • The name of the method under test
  • The state, or condition, which is under test
  • The expected behavior of the test method

Following the method naming, we see a Mockolate method which has not been previously discussed here. The Mockolate stub method allows us to define a Mockolate expectation, in other words, a dependency. Again, a Mock is under test and a Stub is a helper class that is fulfilling a dependency of the CUT and it, itself, is not under test.
In this case we need to stub the getter of the model’s “modelObject” property and check to make sure that it returns a value of type MODEL_OBJECT when the execute method is called on the command. The execute method updates the model’s modelObject property and the getter returns a MODEL_OBJECT object. If it returns a different type or null, then our test will fail. If it successfully returns a MODEL_OBJECT type, then it will pass.
Now, to write our command class so we have something to test. First, write the basic shell of the command with an empty execute method and run the test. The test will fail, perfect! Now, lets make the test pass:

public class MyCommand extends Command
{
	[Inject]
	public var model:IModelInterface;
	[Inject]
	public var event:MyEvent;

	override public function execute() : void
	{
		if ( event.myObject ) {
			model.modelObject = event.modelObject;
		}
	}
}

The MyCommand class injects the model, mapped to its interface, as well as the event which has our payload to update the model. The execute method checks to see if myObject payload exists on the event, which it will because we are providing that in our test’s setup, and then updates the model with the event modelObject. We run our test again…Pass!! Excellent! At this point we look and see if we need to refactor our command production code, if so, refactor and test again and continue this process until complete.

References:
Mockolate
FlexUnit