Testing

TestBox unit specs for every entity and service, plus integration specs over real HTTP requests.

On this page

Testing

CB Genesis ships with a TestBox suite covering every service and entity, plus integration specs that exercise real requests.

Running tests

box testbox run                                  # All tests
box testbox run directory=tests.specs.unit       # Unit tests only
box testbox run directory=tests.specs.integration # Integration tests only
box testbox run bundles=tests.specs.unit.security.RoleServiceTest  # One bundle

The runner (tests/runner.bxm, wired up by box.json's testbox.runner key) also accepts labels= and excludes=, but no spec in this suite declares a label, so filter by directory or bundle instead. --verbose prints each spec as it runs, and outputFile=/outputFormats= write reports - that is how CI invokes it.

Integration specs need a running server

They issue real requests, so box server start must be up and the database migrated and seeded first. CI does exactly that before box testbox run.

Test structure

tests/
├── Application.bx              Virtual ColdBox app (appMapping="/app")
├── runner.bxm                  TestBox CLI runner entry
├── run.bxm / index.bxm         Browser-based runner UI
├── specs/
│   ├── integration/
│   │   ├── MainSpec.bx         Lifecycle events and exception handling
│   │   ├── AuthTest.bx         Login, registration, and password reset
│   │   ├── ProfileTest.bx      Password change and profile validation
│   │   └── SettingsTest.bx     Settings handler CRUD and registry
│   └── unit/
│       ├── security/           APIToken, APITokenService, Permission,
│       │                       PermissionService, RateLimitService,
│       │                       RememberTokenService, Role, RoleService,
│       │                       SecurityService
│       └── system/             AuditLog, AuditLogService, Setting,
│                               SettingService, User, UserService
└── resources/
    └── BaseIntegrationSpec.bx  Shared helper for integration tests

The naming convention is one unit spec per entity and one per service, split by domain folder (security, system) - mirroring app/models. Follow the same pairing when you add your own domain. The runner discovers bundles by the *Spec*/*Test* filename pattern, so either suffix works.

Writing an integration spec

Integration specs extend tests.resources.BaseIntegrationSpec, which wires up appMapping="/app" so paths resolve exactly like production:

component extends="tests.resources.BaseIntegrationSpec" {

    function run(){
        describe( "Registration", () => {
            it( "renders the registration form", () => {
                var event = execute( event = "Auth.register", renderResults = true );
                expect( event.getValue( "cbox_rendered_content" ) ).toInclude( "register" );
            } );
        } );
    }

}
Always reset state in beforeEach()

Call setup() in beforeEach() for every integration spec, so state from one test never leaks into the next.

The checked-in suite is 185 specs across 19 suites: unit coverage for every security and system entity and service, plus integration specs for the application lifecycle (MainSpec), the authentication flows (AuthTest), the profile handler (ProfileTest), and the settings handler (SettingsTest). There is no integration coverage yet for the Users, Roles, Permissions, or AuditLog admin handlers - add it as you build on them; a feature is not covered merely because its service has a unit spec.

Edit this page Download Markdown Last updated Sep 16, 2026, 5:50:56 PM