ChangeWatcher – Watch Out!

Posted May 16th, 2011 by JeffBNimble with No Comments

Like today, at band camp I was trying my best to be a good Flex developer and use ChangeWatcher carefully to watch changes made to a public property. But, I could not for the life of me get it to work. After several hours of debugging and head scratching, I asked Twitter-verse and also some of my co-workers. One of them, (giving credit where credit is due) Jay Proulx made a comment that led me down the road to victory.

The Problem

Before I go any further, let me clarify the problem. I had written a class with a very simple public property and annotated it with the [Bindable] metadata tag. However, as I normally do, I specified my own event. Being a good Flex developer, I typically follow this practice as shown below.

By specifying my own event type, the Flex compiler will not generate any binding code on my behalf. However, what I did not realize was that doing so would prevent my ability to use a ChangeWatcher to watch changes to this property (as shown below). The code that was attempting to watch changes to the “name” property was not causing a ChangeWatcher to do anything. Specifically, my event handler was not being invoked when the property was being changed. In summary, ThisClass was watching a property on ThatClass, but it wasn’t working and I could not figure out why.

A solution, but not THE solution

I noticed that when I removed the event parameter in the metadata, suddenly my code began working (as shown below). But why?

I know that the Flex compiler generates code on my behalf when it encounters a [Bindable] metadata tag. An example of what it generates and compiles is shown below. Essentially, you can tell that the compiler renames the public property (and prefixes it with some unique value) and generates a public getter and setter.

The interesting code here is in the setter. The compiler generates code to conditionally dispatch a PropertyChangeEvent if the new property value is different than the original value. Fair enough, but why won’t the ChangeWatcher work when I have an event type in my metadata?

Before I tell you, have a look at my final solution.

The final solution

After discovering what the problem is, I settled on this solution. It was a tad more work than I wanted, but it works. Personally, I would consider this a bug in the Flex ChangeWatcher code (mx.binding.BindabilityInfo to be specific).

Explanation

It turns out that the ChangeWatcher code will only hookup a ChangeWatcher if the [Bindable] metadata tag is annotating an accessor (getter) or a method. In this case, the new code annotates the getter, which is an accessor. My original code did not work because the [Bindable] metadata tag was annotating a variable (not an accessor or method). And we already know that the compiler does not generate code on your behalf when you specify an event parameter in the metadata tag. Consequently, the ChangeWatcher that was created was not hooked up and didn’t respond to any changes made to the “name” property I thought it was watching. It was not watching.

In my opinion, the ChangeWatcher code should hook itself up properly whether the [Bindable] metadata tag is annotating a variable, accessor or method.

Make a mental note of this in case you run across it in your Flex travels. It might just save you a few hours of work.

Disclaimer

For those of you that want to tell me that I shouldn’t use ChangeWatchers or that my sample code has holes in it, I already know this. I know the dangers of ChangeWatchers and I use them sparingly. I also know to unhook them when I’m done because not doing this potentially results in memory leaks. Feel free to leave me comments….unless you’re going to tell me about the evils of ChangeWatchers or that my sample code has all sorts of holes in it

Mocking: Part 2 – Mockolate covered unit tests

Posted May 5th, 2011 by JeffBNimble with 3 Comments

Introduction

In Part 1 of this blog series on mocking, I covered some high level concepts. If you have yet to read that, I encourage you to do so before you read Part 2. It will help set the stage for what I will cover next.

In Part 2, we will look at how mocks are used and how they will help make you a master at writing unit tests.

Enter Mockolate

For the remainder of this post, I will refer to my favorite ActionScript mocking library; Mockolate. Mockolate is an open source library written by Drew Bourne, who hails from down under. I was fortunate enough to meet Drew in person at 360|Flex in Denver this past April. I sat beside him to learn even more about how to use Mockolate properly.

I’m jealous of Drew for two main reasons. First, he’s incredibly smart and talented. Secondly and arguably more importantly, he has lots of hair that sticks up in the air and that is something I can never have.

I won’t recount how to setup Mockolate for use on your projects. Drew has lots of documentation to help you get started in that regard and I won’t duplicate his efforts. Grab the Mockolate .swc, the other dependent libraries, drop them in your libs folder and you’re ready to roll.

I will utilize the latest features of Mockolate and those require FlexUnit 4.1 or greater. If you are unable to use FlexUnit 4.1 and are stuck on a previous version and want me to write a brief post on that, leave me a comment and I’ll be more than happy. Using Mockolate under FlexUnit 4.0 or earlier requires a slightly different approach.

Unit Testing 101

Before we dive into Mockolate and how to use mocking to significantly improve your unit testing, I want to discuss unit tests conceptually to get everyone on the same level. If you are unfamiliar with the art of unit testing, I will write on that topic in the very near future. Until then, let me cover some high level concepts.

A unit test is a piece of code executing another piece of code and verifying some condition at the end. In Part 1, I talked about the class under test. When writing unit tests, you are exclusively focused on the class under test and that it behaves as desired when you invoke its functions.

Unit tests written against the FlexUnit framework progress through a predictable lifecycle when executed. There are three general phases to the execution of a test case:

  1. Setup
  2. Test execution
  3. Teardown

The Setup phase

Though your unit tests often have many individual test functions on a test class, the FlexUnit framework actually creates and destroys an instance of your test class for each test function. For each test function, the first step is to set the test up. In this phase, a new instance of the class under test is typically constructed, any dependencies of the class under test are constructed and manually injected/set into the class under test and this includes the construction and often the preparation of mocks.

The Test Execution phase

Once the test has been setup, a single test function is executed. Each function typically tests a single public function under a specific usage scenario and verifies one thing at the end. As you improve your test writing skills, you’ll find that most tests are no more than 3-5 lines of code. Consequently, you may end up with many test function. One simple public function on the class under test may execute under numerous different scenarios and have all sorts of interactions that must be verified.

The Teardown phase

After each test function on the test class is executed, FlexUnit enters the teardown phase. This provides the test an opportunity to cleanup. I have found that most of my tests do not utilize this phase since each test is self-contained and there are no side effects. In my opinion, the teardown phase is used more often when writing integration tests that have more side effects (i.e. connecting to a remote service).

The MockolateRule

Mockolate utilizes a FlexUnit 4.1 feature that makes setting up and preparing your mocks about as simple as possible. The MockolateRule is a FlexUnit rule that performs all the magic with minimal effort on your part. FlexUnit rules are AS3 classes that provide advanced setup and teardown capabilities.

In order to utilize the MockolateRule, you simply need to declare a public variable on your test class, instantiate the MockolateRule and annotate it with the FlexUnit [Rule] metadata tag as shown below.

Setting up your mocks

The next step in the process is to let Mockolate generate and prepare your mocks for you. It’s so simple, you’ll be mocking in no time.

Simply identify which dependencies of your class under test need to be mocked. For each, declare a public variable on your test class and annotate each with the Mockolate [Mock] metadata tag as shown below:

During the setup phase of each test, Mockolate will generate a fake ILoginService for you and inject it into your public variable. You can declare as many mocks as you wish AND you may declare mocks as interfaces or concrete classes.

If you’re not amazed at what just happened, go back and re-read this section. Mockolate generated a fake version of the declared variable type on your behalf, created an instance of it and injected it into your variable and it took you all of one line of code and one metadata annotation for each. You did not have to write your own fake implementation.

So what does the mock do? Well, nothing yet. But, it is a fake stand-in for the real thing and you can inject it into your class under test and your class under test is none the wiser.

Setting up the test

So far, we’ve done a lot with mostly no effort. The next step is to perform our own setup. In FlexUnit, this is done by annotating one or more public functions with the FlexUnit [Before] metadata tag. FlexUnit will invoke these functions for each test after the rules have been run (i.e. your mocks have all been generated).

What we want to do in our setup is to create an instance of our class under test and store it in a declared variable in our test class, as shown below (using our LoginCommand from part 1 as an example).

That’s it! We’re setup. We now have an instance of our class under test and it has been initialized with all of the dependencies it needs in order to work properly. It should be noted that you don’t have to set every single dependency on your class under test. Only the dependencies that are used during the execution of tests need to be set.

Our first unit test using a mock

We’re now ready to write our first test method. In Part 1, I noted the various things we might wish to test against our LoginCommand. For reference, I’ve copied these testable scenarios below.

  1. Verify that the LoginCommand invokes the ILoginService.login function passing the username and password when both are specified
  2. Verify that an error is thrown when the UserCredentialsVO contains a null username
  3. Verify that an error is thrown when the UserCredentialsVO contains a null password
  4. Verify that an error is thrown when the UserCredentialsVO contains a blank username
  5. Verify that an error is thrown when the UserCredentialsVO contains a blank password

The only public function containing logical code in the LoginCommand is the execute() function. Since the LoginCommand is a relatively simple class with only one public function, I’ll have only a handful of tests. The execute() function accepts a single argument; an instance of LoginCredentialsVO. This class is a simple Value Object model class that contains only data. For a very simple class such as this, which happens to be a dependency of the LoginCommand, there is really no compelling reason to mock this. Since the VO class does not pull in any of its own dependencies and adds no further complexity to the unit test, I’ll simply use the real class.

Here is the test function for the first scenario:

There it is. That’s my first test. You might be scratching your head wondering what in the wide world of sports is going on. There is actually a lot going on here, despite the fact that the entire test consists of 3 lines of code. Let’s take a closer look.

Lets start with the name of the function. It might look a bit odd to you since it certainly isn’t the convention most of us use to name functions. The convention I use begins with the name of the function being tested on the class under test; execute. The next piece of the function name is the scenario being tested; I’m using valid login credentials. The third part of the name is the expected result of the test; the login service should have been invoked. I’ll cover this sort of thing in more detail in a future blog post regarding unit testing. Nonetheless, you can quickly tell what the test is doing just by reading the function. Separating the tuple by underscores makes it a bit easier to read rather than camel-casing the entire lengthy name.

The first line of code in the test function is setting an expectation (as described in Part 1). Using Mockolate’s mock() function instructs Mockolate to keep track of what happens to the loginService mock prepared earlier. The line of code essentially says please mock the login function on the login service because I expect that function to be invoked with the specific arguments listed (literal values in this case) and I expect it to be invoked one time. I did all of that with one line of code, rather Mockolate allowed me to do all of that. I can actually mock as many different things as I wish prior to executing the function I’m testing.

The next line is obvious. An instance of LoginCredentialsVO is constructed to be used to pass to the execute() function of the LoginCommand.

The last line of the test function invokes the function on the class under test that I’m testing.

If you recall from Part 1, mocking often involves setting expectations and then verifying that those expectations are met. The first line of the test function is where I set my expectations. But, where did the verification step occur? The MockolateRule that was created handles that automatically at the end of each test. It verifies everything that was mocked at the end of the test. If the expectation(s) are not met, Mockolate fails the test. In other words, if the mocked ILoginService.login function was not invoked with these specific arguments exactly one time during the test, the test fails.

If I were using a real implementation of the ILoginService, (i.e. HTTPLoginService) that actually attempted to communicate over the network and invoke a real service, the complexity increases significantly as does the probability that other factors will cause my test(s) to fail. Instead, the mock allows me to focus exclusively on the class under test. Who cares whether a login actually occurs? I’m testing that the command works as expected.

Our second unit test

Before I show you the source code for the entire test class, let’s look at a second test that verifies the second scenario listed from above. This one is slightly different in that an error is thrown if an invalid username is passed along. The feature that allows me to deal with errors is provided by FlexUnit, but is worth examining regardless.

The test is shown below:

This test is even simpler at only two lines. Notice the metadata annotation for the test function. It adds an “expects” parameter with a reference to the fully qualified name of the class of the Error that is expected. FlexUnit will pass the test if an instance of Error is thrown or fails the test if no Error is thrown.

One more unit test using a mock

One rule of unit testing is that each test function should assert or verify one and only one thing. I pass a null username in the test above and verify that an Error is dispatched. However, I might also wish to verify that the ILoginService.login function was not invoked.

While I could easily combine both of these into a single test, it is important to keep them separate so that a failure easily indicates what the root cause was. Notice that I had to leave the “expects” parameter in the metadata tag because the command will still throw an Error. However, I’ve added back my mock() function, but set the expectation that this function will not have been called under any circumstances. Specifically, I’m setting the expectation that the login function on the mocked ILoginService will never be invoked with any combination of arguments.

Mockolate uses the Hamcrest library for matching. A description of Hamcrest is beyond the scope of this blog post, but feel free to read up on it. Hamcrest was ported to AS3 by none other than Drew Bourne. I told you that dude was smart.

The full test class

Summary

I’ve barely scratched the surface of what Mockolate (and mocking in general) can do for you and the unit tests you write. I didn’t cover stubbing or strict vs. nice mocks or several other Mockolate features you’ll use frequently. I will save that for an upcoming post (Part 3?). Regardless, you should notice a number of things about the unit test.

  1. I wrote several test functions to adequately cover the LoginCommand
  2. Each test was no more than 3 lines, several were only 2 lines
  3. Mockolate did much of the heavy lifting for me with minimal effort
  4. Setup was a breeze, minimal coding required
  5. Mocking allows me to focus exclusively on the class under test
  6. I wrote the entire test class in under 5 minutes
Twitter