Analyst 18   Software Engineering and other random() subjects

ColdFusion - Testing FW/1 Controllers with TestBox

Some frameworks allow you to test your controllers directly - usually a faster approach to using Selenium and headless browsers.

I decided to try that for a new FW/1 app, but since I could only find discussions on how to do that, and not a lot of code, I decided to try that on my own, using TestBox.

This picks up where my FW/1 Example Application Articles left… I suggest you read that in case any of the code seems confusing.

A Test Spec for controllers

Test_7_Controllers.cfc [view full source]:

/**
 * Tests the Application's controllers
 *
 */
component extends="testbox.system.BaseSpec"{

    // executes before all suites
    function beforeAll(){
        // reinitialize ORM for the application
        ORMReload();

        // invoke controller object
        mainController = createObject("component", "root.home.controllers.main");

        // injects the FW/1 framework into the tested controller
        mainController.framework = createObject("component", "framework.one");

        // binds service to main controller
        mainController.clippingService = createObject("component", "root.home.model.services.clippingService");

        // Mock request context struct
        rc = structNew();

        //creates fake data for tests
        ..........
        }
    }

    ...

In TestBox beforeAll() runs once, before any test, so this is where we invoke the main controller and inject its dependencies for this test case:

  • framework - An instance for FW/1
  • clippingService - The service that is queried by this controller

We also create a mock rc struct that will be used to pass data to and from the tested controller and insert some test data on the test database.

Now for the test proper:



    function run( testResults, testBox ){

        describe("Main Controller: ", function(){

            beforeEach( function( currentSpec ){
                // don't let rc data persist through tests
                structClear(rc);
            });

            it("The DEFAULT method returns an ORM object with an array of articles", function(){
                // execute default method
                mainController.default( rc );
                expect( structKeyExists(rc, "qry_clipping")).toBeTrue();
                expect( rc.qry_clipping.count).toBe( 20 ); // total records
                expect( arrayLen(rc.qry_clipping.data) ).toBe( application.recordsPerPage ); //records per page
            });

        });

    }

}

As you can probably guess, the beforeEach() closure runs before every test in its describe block, and in this case it resets the rc struct so request data does not persist among tests (we only have one test here, but in my real app this was happening).

The it() block shows how to execute the default method in the main controller and how to test that the response is accurate.

There you go! Now we can stick to using Selenium only when and where it’s really needed.


The source code for this project is hosted on the fw1-clipping github page.