<cffunction name="fakeRelocate" access="private" returntype="void" output="false">
<cfargument name="url"/>
<cfabort showerror="Location: #arguments.url#"/>
</cffunction>
The question is: how do we replace ColdBox's function?
ColdBox provides a lot of 'events' in its lifecycle and you can write CFCs to intercept any of them. One of them is afterHandlerCreation so in theory you could write an interceptor for that which patched the runtime instance.
Unfortunately, the ColdBox documentation didn't say how that event worked! I pinged Luis and he promptly updated the documentation and here is how you do it:
Create an interceptor to do the patching - I called mine test.mock.interceptor.HandlerRelocatePatch:
<cfargument name="url"/>
<cfabort showerror="Location: #arguments.url#"/>
</cffunction>
<cfcomponent output="false">
<cffunction name="afterHandlerCreation" access="public" returntype="void" output="false">
<cfargument name="event" type="any"/>
<cfargument name="interceptData" type="struct"/>
<cfscript>
// fake out the base handler relocate() method: interceptData.oHandler._fakeInjector = variables.methodInjector;
interceptData.oHandler._fakeInjector( "relocate", variables.fakeRelocate, true );
</cfscript>
</cffunction>
<cffunction name="methodInjector" access="private" returntype="void" output="false">
<cfargument name="methodName"/>
<cfargument name="methodBody"/>
<cfargument name="injectPublic" default="false"/>
<cfset variables[arguments.methodName] = arguments.methodBody />
<cfif arguments.injectPublic>
<cfset this[arguments.methodName] = arguments.methodBody />
</cfif>
</cffunction>
<cffunction name="fakeRelocate" access="private" returntype="void" output="false">
<cfargument name="url"/>
<cfabort showerror="Location: #arguments.url#"/>
</cffunction>
</cfcomponent>
Once registered (see below), this is called after each event handler is created and it first injects a new public method called _fakeInjector (as a copy of the methodInjector code in the interceptor) and then it calls that new method to perform the injection of the private method relocate()!
All you need to do is register the interceptor in your test case:
<cffunction name="afterHandlerCreation" access="public" returntype="void" output="false">
<cfargument name="event" type="any"/>
<cfargument name="interceptData" type="struct"/>
<cfscript>
// fake out the base handler relocate() method: interceptData.oHandler._fakeInjector = variables.methodInjector;
interceptData.oHandler._fakeInjector( "relocate", variables.fakeRelocate, true );
</cfscript>
</cffunction>
<cffunction name="methodInjector" access="private" returntype="void" output="false">
<cfargument name="methodName"/>
<cfargument name="methodBody"/>
<cfargument name="injectPublic" default="false"/>
<cfset variables[arguments.methodName] = arguments.methodBody />
<cfif arguments.injectPublic>
<cfset this[arguments.methodName] = arguments.methodBody />
</cfif>
</cffunction>
<cffunction name="fakeRelocate" access="private" returntype="void" output="false">
<cfargument name="url"/>
<cfabort showerror="Location: #arguments.url#"/>
</cffunction>
</cfcomponent>
// fake out the base handler relocate() method:
getController().getInterceptorService().registerInterceptor(
interceptorObject = createObject("component", "test.mock.interceptor.HandlerRelocatePatch")
);
Happy testing!getController().getInterceptorService().registerInterceptor(
interceptorObject = createObject("component", "test.mock.interceptor.HandlerRelocatePatch")
);

6 responses so far ↓
1 Tyler Clendenin // Aug 8, 2009 at 11:43 AM
2 Sean Corfield // Aug 8, 2009 at 12:32 PM
3 Sami Hoda // Aug 9, 2009 at 11:24 PM
I'd benefit from a post on Hudson too. Look forward to it!
4 John Allen // Aug 10, 2009 at 8:26 AM
About two write a bunch of tests for some FW/1 controllers... this post is Timely. Thanks.
5 Sean Corfield // Aug 10, 2009 at 11:20 AM
So, yes, you'd want the try/catch around the controller test but you can use standard mocking techniques with FW/1.
6 John Allen // Aug 10, 2009 at 1:15 PM
I've become a FW/1 convert. It truly rocks.
Thanks Sean.
Leave a Comment