Testing controllers?

63 views
Skip to first unread message

ehm77

unread,
Feb 1, 2012, 1:36:21 PM2/1/12
to framework-one
What's the best practice on testing controllers in FW/1?

We have pretty good coverage of our model using MXUnit, but we are
rapidly changing and trying to develop some standards, so we want to
ensure deployed code is not adversely affected.

For example, we are standardizing our method names...this is fine in
the model, if we have tests, problems are caught fairly quickly.
However, we also need to update the controller that is invoking those
services. We've just been search/replacing the old method names. I'd
like to find a more structured approach to ensure these changes can be
rolled out and we can be confident that all the controllers have been
updated.

Fabiano

unread,
Nov 5, 2015, 1:33:56 PM11/5/15
to framework-one
This post is a bit old, but I'm bringing it up since I was researching the same topic and will hopefully get some more insight.

Not sure about "best pratices" as I just added a controller test for a new project, but here's how I did it (using TestBox instead of MXUnit).

Some pre-testing setup:

component extends="testbox.system.BaseSpec"{

   
// executes before all suites
   
function beforeAll(){

       
// 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
       
..........
       
}
   
}

And for a test example:


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
           
});

       
});

   
}



If anyone is interested, I go into a bit more detail here:

Testing FW/1 Controllers with TestBox



This runs MUCH faster than the Selenium based integration tests (which, of course, have their place), but I'd love to hear about cons to this approach...I might be missing something :)

Sean Corfield

unread,
Dec 26, 2015, 3:46:39 PM12/26/15
to framew...@googlegroups.com
Fabiano wrote on Thursday, November 5, 2015 at 10:33 AM:
This post is a bit old, but I'm bringing it up since I was researching the same topic and will hopefully get some more insight.

Bit surprised no one ever responded to this. I wanted to wait a while and see what feedback you got before jumping in… so here’s my 2¢ at this point.

Not sure about "best pratices" as I just added a controller test for a new project, but here's how I did it (using TestBox instead of MXUnit).

Testing controllers is a thorny subject. Unit testing focuses (or should focus) on small pieces of functionality: objects in isolation, or even just methods in isolation. Testing at the controller level is coarser-grained and tests a lot of moving pieces all at once so it’s not "unit testing", even if you’re mocking absolutely everything (including the FW/1), so you’re into "integration testing" at this point.

You’re right that testing controllers end-to-end is easier / faster than Selenium / WebDriver level testing (well, usually easier) but you have to be very careful since your controllers typically rely on framework behavior and that can be very hard to setup correctly (I.e., to match what really happens in a request). For example, FW/1 relies on `onApplicationStart()`, `onSessionStart()`, `onRequestStart()` all being called appropriately to run the various setup methods. Even a regular request is going to rely on `onRequest()` for all of the processing to occur exactly like a web request. And then `onRequestEnd()` is also invoked automatically.

Since you’re not doing any of that in your test setup, there’s a lot missing from the "model" you’re testing against so your controller might have completely different behavior in the context of a real request (calling `fw.abortController();` and `fw.redirect();` are good examples).

It’s because of that (difference between the test model and the real world model), that I generally don’t recommend testing controllers like this: it’s really hard to get the behavior to match so you can be testing the wrong thing. I’m not saying there’s no value in attempting such testing, just warning that it’s hard and potentially misleading.

That’s also why I’m never attempted to provide a testing mock of the framework itself: providing such a test harness would be misleading, because it would sanction this kind of testing, and I don’t believe I could mock enough of the framework’s behavior accurately enough to ensure that users’ controller-level testing was "doing the right thing".

So, bottom line, I’m glad you’ve found value in doing this but I don’t recommend it :)

Sean Corfield -- (904) 302-SEAN
An Architect's View -- http://corfield.org/

"Perfection is the enemy of the good."
-- Gustave Flaubert, French realist novelist (1821-1880)

Fabiano

unread,
Dec 27, 2015, 11:32:54 AM12/27/15
to framework-one
Thank you for the thoughtful reply, Sean.

We are definitely in agreement in regards to the shortcomings of this method and, to be honest, I'm still on the fence about its inherent value (precisely due to the issues you raised).

I had some free time and wanted to experiment with the idea after a period of writing tests for Python based apps :)

Reply all
Reply to author
Forward
0 new messages