Using Mocks during record state

As we've started using easymock here in our CF development I've logged a few issues that have occurred when developers who aren't familiar with mocks begin using them in their unit tests.

Take the example below:

<cfcomponent name="ExampleTest">
<cffunction name="setup" returntype="void">
<cfset mf = createObject( "component", "easymock.MockFactory" ) />

<cfset mock = mf.createMock( "component.to.Mock" ) />

<cfset test = createObject( "component", "Example" ).init( mock ) />
</cffunction>

<cffunction name="testFunction" returntype="void">
<cfset mf.expect( mock.functionCall() ).andReturn( true ) />

<cfset mf.replay( mock ) />

<cfset assertTrue( test.function(), "function() failed" ) />

<cfset mf.verify( mock ) />
</cffunction>
</cfcomponent>

At first everything looks fine. The mock is created and passed to the component under test in the setup. The expected functions are called on the mock and it is set to replay. The test function runs and then the mock behavior is verified.

But what you don't see here is what happens to the mock when it is passed to the Example component in init().

<cfcomponent name="Example">
<cffunction name="init">
<cfargument name="obj" />

<cfset foo = arguments.obj.otherFunction() />

<cfreturn this />
</cffunction>
</cfcomponent>

What's this? A function call is made on the component we pass into Example.init(), in this case our mock. Since the mock has not been set to replay, the otherFunction() call is recorded. Which will cause the test to throw an error on verify.

To remedy this, the initialization of the Example component simply needs to happen in the test function, after replay.

Make sure your mocks are in replay mode before using them.

Comments
BlogCFC was created by Raymond Camden. This blog is running version 5.5.006. | Protected by Akismet | Blog with WordPress