Search code examples
coldfusioncfcmxunit

What's the best way to unit test a cfc that uses a Java object for a lot of its functionality?


I have a cfc that relies heavily on a Java object (created via JavaLoader) for a lot of its core functionality that I'd like to write some tests for and I'm not sure what the best way to do this is. Here is an example of a method I'd like to write a test for with instance.note being a java object.

<cffunction name="getNotes" returntype="Array" access="public" output="false" hint="I return a list of a users notebooks" >
    <cfargument name="maxCount" type="numeric" required="false" default="9999" hint="The maximum number of notes to get" />
    <cfscript>
        if(arguments.maxCount)
            return instance.note.listNotes(maxCount);
        else
            return instance.note.listNotes();
    </cfscript>
</cffunction>

One thing I thought of doing is creating a stub CFC that has the same method names and similar return values and then mocking that stub and injecting it?


Solution

  • When we needed to unit test CF functions that relied upon Java objects (which we did a LOT of), we used Mockito to mock the Java objects.

    So, hoping this code snippet makes sense, its been almost a year since I've done this:

    <cfcomponent displayname="TestWhatever" extends="mxunit.framework.TestCase" output="false">
    
        <cffunction name="setUp" access="public" returntype="void">
          <cfscript>
            // named it mk for keeping it short
            variables.mk = createObject("java","org.mockito.Mockito");
    
            //Create the mock object
            variables.mockNote = mk.mock(createObject("java","com.company.whatever.note").getClass());
    
            // Mock Data
            fullList = {whatever listNotes() returns}
            partialList3 = {whatever listNotes(3) returns}
    
            //some common mocking
            mk.when(variables.mockNote.listNotes()).thenReturn(fullList);
            mk.when(variables.mockNote.listNotes(mk.eq(3))).thenReturn(partialList3);
            mk.when(variables.rootOrgObj.guid()).thenReturn("root");
    
            // Assign the mock object to where your CFC expects it.
            instance.note = variables.mockNote
          </cfscript>
        </cffunction>
    
    </cfcomponent>
    

    Having said that, if your sample function is real, there's really no point in unit testing it. Its simply not doing anything but being a proxy to the java object. There is no significant logic in there to test.

    Since you have a default on the cfargument, it will always exist (again, I think so, its been a year since I've done CF), so your guard statement isn't even required - the first code path will always be called, with the passed maxCount if specified, or with 9999 if not.