Unit Testing 101
A unit test isolates and executes a small part of your software and compares the result with your expectations. The small part of your software being tested is generally called the Software-Under-Test (SUT). Isolation of the software (SUT) is improved when you fake the dependencies. Faking the dependencies is called 'Mocking'. Mocking will be covered in the next post in this series.
How to Unit Test in ColdFusion
First, let's download MXUnit. MXUnit is a Unit Testing Framework for CFML and works well on Adobe ColdFusion, Railo and Open BlueDragon. You can simply drop the download into your Web root (or map a path using the ColdFusion Administrator).
Now, we need to write our test. We write our test first (before we have written software) to help us stay true to our discipline of testing. We also write our test first because we only have an expectation of how our SUT will work. This is the perfect time to test since our test is the verification of our expectation!
So, let's breakout the IDE and write some code. My first example will test a simple Validation Service that wraps the Hyrule Validation framework built by Dan Vega. I have wrapped Hyrule with a Validation Service to allow me to swap Hyrule for another validation solution should there ever be a need.
Build the Test
component
// Extend MXUnit
extends="mxunit.framework.TestCase"
/** Constructor */
public void function setUp() {
// Setup here...
}
/** A test ... */
public void function testGetValidator() {
// Test here...
}
} // ...
/** Constructor */
public void function setUp() {
/* Create a new User object. This is the object the
validation service will be validating. */
_User = new appcore.model.objects.User();
/* Create the Software-Under-Test (SUT) */
ValidationService = new appcore.model.services.ValidationService();
}
/** Test the validation service to confirm
it returns the expected Validator */
public void function testGetValidator() {
/* AssetIsTypeOf is part of the MXUnit API. We confirm the object
returned by my service has the class path 'hyrule.Validator' */
assertIsTypeOf(ValidationService.getValidator(),"hyrule.Validator");
}
// ...Our first test will verify that the Validation Service returns the object I expect: Hyrule. MXUnit will execute the setup method before firing any tests in the unit test. So, in my setup method I will create a new User object and a instance of the Validation Service. These objects will then be available to each individual test method in the component.
component extends="mxunit.framework.TestCase" {
/** Constructor */
public void function setUp() {
_User = new appcore.model.objects.User();
// SUT
ValidationService = new appcore.model.services.ValidationService();
}
/** Test the validation service to confirm
it returns the expected Validator */
public void function testGetValidator() {
assertIsTypeOf(ValidationService.getValidator(),"hyrule.Validator");
}
/** Test the validation service to confirm
it fails when User has invalid data */
public void function testValidationUserFail() {
_User.setEmail('aaron');
_User.setPassword('');
assertFalse( ValidationService.validate(_User),'Should return false when object has invalid data' );
}
/** Test the validation service to confirm
it passes a valid User object */
public void function testValidationPass() {
_User.setEmail('aarongreenlee@gmail.com');
_User.setPassword('passw0rd!');
assertTrue( ValidationService.validate(_User), 'Should return true when a object has valid data.' );
}
}
