Home >
Validation in Flex with Hamcrest-AS3
Hamcrest? No, it isn't a fancy sandwich topping. Hamcrest is a framework for creating matchers, allowing matching rules to be defined declaratively (from Wikipedia). Hamcrest has been used by many popular unit testing frameworks including JUnit and FlexUnit 4. Hamcrest-AS3 is not itself a unit testing framework, but it provides extended capabilities for providing assertions that aren't possible with simple assertEquals() style assertions.
While unit testing is an obvious use case for Hamcrest-AS3, it is also very effective as a validator for Flex forms. It provides complex matching that is difficult or impossible to accomplish with the standard library of validators tat Flex supplies. This article will serve as an introduction to using Hamcrest-AS3 for form validation, and hopefully an introduction to the general concepts behind Hamcrest-AS3 matching on the whole.
Hamcrest-AS3 is a port of the popular Java library. It was ported by Drew Bourne and is available on github.
Flex 3.* is packed with a number of common validators that are useful for typical forms. DateValidator, EmailValidator, StringValidator, and a host of other validators provide a good start for your validation needs. The problem comes in when your validation needs start to become more complex. What if you have a ComboBox that contains custom data objects and you want to make sure that the selected item matches specific criteria? What if you have a password input field accompanied by a password conformation field that needs to be validated before a user can proceed? Typically this would mean that you would need to extend the base Validator class and write your own custom validation to handle these specific use cases. Hamcrest-AS3 provides a simple set of tools that makes this easy, without needed to create custom classes. You can do complex validation directly in your component via declarative MXML.
String Object Matching:
<validator:MatcherValidator
id="passwordMatchValidator"
source="{passwordConfirmationInput}"
property="text"
errorMessage="Password must match confirmation"
required="true">
<hamcrest:AllOf>
<hamcrest:EqualTo value="{passwordInput.text}"/>
</hamcrest:AllOf>
</validator:MatcherValidator>
The Hamcrest-AS3 library is equipped with an MXML compatible class called MatcherValidator. The extends the Validator base class, and has the typical validator properties. You assign it a source, tell it what property to look at on the source, and all of the other standard validator options. The fun starts inside of the MatcherValidator where we add the Hamcrest-AS3 matcher. There are a number of core matchers available in Hamcrest-AS3. There is a complete list here. In this case, we are making use of the "AllOf" matcher, that looks at all of the supplied parameters and ensures that they all have a true result. Like a boolean statement in regular AS3 syntax, the Hamcrest-AS3 AllOf matcher "short-circuits" when it meets its first false result. This is similar like this to:
true && true && true && true //simplistic, obviously.
The above example is using a Hamcrest-AS3 equalTo object matcher to compare two objects. In this case we want to ensure that one String object (the passwordInput.text object) matches another String object (the passwordConfirmationInput.text object). The names of the matchers generally define what we want them to provide. "Is this object equal to this object" in the case of the password confirmation example.
Object Matching:
<validator:MatcherValidator
id="myObjectSelector"
source="{myObjectCombo}"
property="selectedItem">
<hamcrest:AllOf>
<hamcrest:InstanceOf type="{MyObject}"/>
<hamcrest:HasProperty property="myProperty" value="{notNullValue()}"/>
</hamcrest:AllOf>
</validator:MatcherValidator>
This example is again using object matches, but in this case we are using the InstanceOf and HasProperty matchers. InstanceOf, as the name suggests, checks to see if our ComboBox's selected item is an instance of a particular class. The HasProperty matcher checks the selected item for the its myProperty and makes sure that it is a not null value. You can begin to see here how chaining these matchers can provide for some complex validation.
Date Matching:
<validator:MatcherValidator
id="myDateInputValidator"
source="{myDateChooser}"
property="selectedDate">
<hamcrest:AllOf>
<hamcrest:DateBetween min="{new Date(1920, 1, 1)}" max="{new Date(2200, 1, 1)}"/>
</hamcrest:AllOf>
</validator:MatcherValidator>
This example is using the Hamcrest-AS3 DateBetween matcher. Flex does have a date validator, but it is simplistic and is strictly for checking the format of a date string. Hamcrest-AS3 provides several powerful date matchers that work off of AS3 Date objects to provide validation.
String Matching:
<validator:MatcherValidator
id="mytextInputValidator"
source="{myTextInput}"
property="text">
<hamcrest:AllOf>
<hamcrest:EndsWith string="me"/>
<hamcrest:StartsWith string="Ham"/>
<hamcrest:MatchesPattern flags="g" expression="\\s+"/>
</hamcrest:AllOf>
</validator:MatcherValidator>
This is utilizing the Hamcrest-AS3 string matchers. With the above, if our text input had the text "Hamcrest-AS3 is freakin awesome" it would be validated. StartsWith and EndsWith are self explanatory. MatchesPattern uses a regular expression, and in this case is looking for any white space.
This really only scratches the surface of what you can do with Hamcrest-AS3 for validating forms. It seems a little daunting at first, foreign even, but with a little effort to grasp the concepts it starts to make sense. Being able to build rules declaratively has lots of uses. Validation is just one. Hopefully this has given you some ideas on how you might make use of Hamcrest-AS3 in your projects.




Facebook Application Development
Great stuff! Never thought to use matchers outside of unit tests.
Thanks!
Thanks for this post, I didn't kow about it.
sounds great, i might have to try this on my new site,
Microsoft Points codes and see how it work. thanks for your hard work on this.. i know it aint easyy... or maybe its just me :P
Wow, thanks for the insightful post. I look forward to reading more from you.
essay
Wow, thanks for the insightful post. I look forward to reading more from you.
essay