testbox-assertions
Use this skill when using the TestBox $assert object for xUnit-style assertions: isTrue, isEqual, includes, isEmpty, key, instanceOf, throws, between, closeTo, lengthOf, match, null, typeOf, and others; registering custom assertion functions with addAssertions(); or using BoxLang dynamic assertion methods (assertIsTrue, assertBetween, etc.).
TestBox Assertions โ $assert Reference
When to Use This Skill
- Writing xUnit-style assertions using the
$assertobject in test functions - Using the full
testbox.system.AssertionAPI for validation - Registering inline or class-based custom assertions with
addAssertions() - Using BoxLang dynamic
assertXxx()method variants
The $assert Object
Every TestBox bundle receives $assert โ an instance of testbox.system.Assertion. It is available in both xUnit test functions and BDD it() blocks.
function testUserCreation() {
var user = userService.create( { name: "Alice", email: "[email protected]" } )
$assert.isNotNull( user )
$assert.isEqual( "Alice", user.name )
$assert.typeOf( "struct", user )
}
Complete Assertion Reference
Boolean
$assert.isTrue( actual, [message] )
$assert.isFalse( actual, [message] )
Equality
$assert.isEqual( expected, actual, [message] ) // case-insensitive
$assert.isEqualWithCase( expected, actual, [message] )
$assert.isNotEqual( expected, actual, [message] )
Null
$assert.null( actual, [message] )
$assert.notNull( actual, [message] )
Emptiness
$assert.isEmpty( target, [message] ) // array, struct, string, query
$assert.isNotEmpty( target, [message] )
Size / Length
$assert.lengthOf( target, length, [message] )
$assert.notLengthOf( target, length, [message] )
Key Existence (Structs)
$assert.key( target, key, [message] )
$assert.notKey( target, key, [message] )
$assert.deepKey( target, key, [message] ) // recursive search
$assert.notDeepKey( target, key, [message] )
Inclusion (Strings / Arrays)
$assert.includes( target, needle, [message] ) // case-insensitive
$assert.includesWithCase( target, needle, [message] )
$assert.notIncludes( target, needle, [message] )
$assert.notIncludesWithCase( target, needle, [message] )
Type Checks
$assert.typeOf( type, actual, [message] ) // uses isValid() under the hood
$assert.notTypeOf( type, actual, [message] )
$assert.instanceOf( actual, typeName, [message] )
$assert.notInstanceOf( actual, typeName, [message] )
Common type values: array, struct, component, numeric, boolean, date, string, uuid, email, url, query
Numeric Comparisons
$assert.isGT( actual, target, [message] )
$assert.isGTE( actual, target, [message] )
$assert.isLT( actual, target, [message] )
$assert.isLTE( actual, target, [message] )
$assert.between( actual, min, max, [message] )
$assert.closeTo( expected, actual, delta, [datePart], [message] )
String / Regex
$assert.match( actual, regex, [message] ) // case-insensitive
$assert.matchWithCase( actual, regex, [message] )
$assert.notMatch( actual, regex, [message] )
Exceptions
// Assert a closure THROWS
$assert.throws( target, [type], [regex], [message] )
// target must be a closure/function reference
$assert.throws( () => service.delete( 999 ), "NotFoundException" )
$assert.throws( () => service.delete( 999 ), "NotFoundException", "999" )
// Assert a closure DOES NOT throw
$assert.notThrows( target, [type], [regex], [message] )
$assert.notThrows( () => service.safeOperation() )
Force Pass/Fail/Skip
$assert.fail( [message] ) // forcibly fail the test
$assert.skip( message, [detail] ) // skip current test with a message
Generic Expression Assert
$assert.assert( expression, [message] )
// example:
$assert.assert( user.age >= 18, "User must be an adult" )
BoxLang Dynamic Assertion Methods
When running tests in BoxLang, you can call any $assert method as a top-level function by prefixing it with assert:
// Standard $assert style
$assert.isTrue( myBool )
$assert.isEqual( expected, actual )
$assert.between( value, 1, 100 )
// BoxLang dynamic method style (identical behaviour)
assertIsTrue( myBool )
assertIsEqual( expected, actual )
assertBetween( value, 1, 100 )
assertThrows( () => badCall(), "MyException" )
assertCloseTo( 3.14, 3.14159, 0.01 )
Common Assertion Patterns
// Struct shape
$assert.isNotEmpty( responseData )
$assert.key( responseData, "id" )
$assert.key( responseData, "name" )
$assert.typeOf( "numeric", responseData.id )
// Array contents
$assert.typeOf( "array", results )
$assert.isNotEmpty( results )
$assert.lengthOf( results, 3 )
$assert.includes( results, "expectedValue" )
// Exception handling
$assert.throws(
() => userService.findById( -1 ),
"ValidationException",
"-1"
)
// Approximate date equality
$assert.closeTo(
expected: now(),
actual: user.createdAt,
delta: 2,
datePart: "s"
)
Custom Assertions
Inline Registration
Register in beforeTests() (xUnit) or beforeAll() (BDD) to keep assertions clean across specs:
function beforeTests() {
addAssertions( {
isValidEmail: function( actual ) {
return isValid( "email", actual )
? true
: fail( "[#actual#] is not a valid email address" )
},
isUUID: function( actual ) {
return isValid( "uuid", actual )
? true
: fail( "[#actual#] is not a UUID" )
},
hasNoErrors: function( actual ) {
return ( actual.keyExists( "errors" ) && !actual.errors.isEmpty() )
? fail( "Response has errors: #serializeJSON( actual.errors )#" )
: true
}
} )
}
// Usage
function testEmailValidation() {
$assert.isValidEmail( "[email protected]" ) // passes
$assert.isValidEmail( "not-an-email" ) // fails
$assert.isUUID( createUUID() )
}
Class-Based Assertion Library
For shared, reusable assertions across multiple test bundles:
// tests/helpers/AppAssertions.cfc
component {
function assertIsActiveUser( expected, actual ) {
return ( actual.keyExists( "isActive" ) && actual.isActive )
? true
: fail( "User [#actual.name ?: 'unknown'#] is not active" )
}
function assertHasPermission( expected, actual ) {
return ( actual.permissions.findNoCase( expected ) > 0 )
? true
: fail( "User does not have permission [#expected#]" )
}
function assertResponseSuccess( expected, actual ) {
return actual.success
? true
: fail( "Response was not successful. Message: #actual.message ?: ''#" )
}
}
function beforeTests() {
// Single class
addAssertions( "tests.helpers.AppAssertions" )
// Multiple classes
addAssertions( "tests.helpers.AppAssertions,tests.helpers.SecurityAssertions" )
// or array:
addAssertions( [ "tests.helpers.AppAssertions", "tests.helpers.SecurityAssertions" ] )
}
function testAdminUser() {
var admin = userService.findById( 1 )
$assert.isActiveUser( admin )
$assert.hasPermission( "ADMIN", admin )
}
$assert vs expect() Guide
Use $assert when:
- Writing xUnit-style test functions
- You prefer imperative
isEqual( a, b )syntax - You need
assert( expression )for arbitrary boolean checks
Use expect() when:
- Writing BDD specs
- You want fluent chaining:
expect( x ).toBe( y ).toHaveKey( "z" ) - You want
expectAll()for collection assertions - You want custom matchers with
notnegation
Both are available in the same bundle โ mix freely.