Search code examples
coldfusiontestbox

Is it possible to mock a native ColdFusion function call?


I've been refactoring a service we use for LDAP calls and finally getting around to updating our unit test for it.

I want to test the rest of the function and catch the CFLDAP call so it does not go out and do its normal thing - useful for when doing testing without network connections for one, also useful for testing if the function handles errors from CFLDAP as I want it to.

Is there a way to mock the native ColdFusion CFLDAP call so I can prevent the actual call to LDAP as well as spy on the call log/arguments passed to it?

(this is all assuming that the LDAP call works as expected since that is out of my control and not the concern of this unit test)


Solution

  • Short version: no, it's not possible to mock a native ColdFusion function call.

    Longer version: Carl's comment nails the approach one should take here: wrap your <cfldap> call in an adapter, along these lines:

    // YourDirectoryServiceAdapter.cfc
    component {
        
        variables.server = "ldap.example.com"
        // etc other connectivity credentials here
        
        public query function query() { // maybe specify individual cfldap attributes here
            var data = false 
            cfldap(
                name = "data",
                server = variables.server,
                // etc
                attributeCollection=arguments // query-specific attributes
            )
            return data
        }
    }
    

    And then inject this adapter into your service class via your DI container or just as a constructor argument or whatevs. Some mechanism that can be leveraged by your tests to use a test double instead.

    And, yeah, when you come to test your service: pass a test double instead of the "real" YourDirectoryServiceAdapter.

    I recommend against Redtopia's suggestion as it's pretty poor practice to bake testing logic into production code: it adds complexity (which itself then needs tests, and then... you hit recursion issues ;-), breaks the single responsibility principle, runs contrary to other industry-standard practices, and just adds cognitive load to your code. It's just easy to use an adapter as per above.

    NB: really all tags / functions that hit external resources (LDAP services, DB services, the file system, etc) should be abstracted-away into adapters like this, to facilitate streamlining your testability. But start small and work up to that ;-)

    Bravo for being one of the minority of CFMLers who have automated tests, btw.