You would think that given the context of the CFEasyMock package I would have a slurry of unit tests covering all aspects of the project from a very TDD perspective.
Alas, that is not the case. There were scattered tests that didn't cover much, other than basic creation of mocks and simple happy path tests.
Well, that has changed, or at least has mostly changed. I've gotten about 40% coverage now, and the unit tests use the CFEasyMock package.
I've found that the greatest benefit of CFEasyMock so far, has been the near elimination of having to do stepwise debugging to find out what a particular method is doing. You know the drill, code in output so you can see where things are happening. Run the method, dump values, see where things are occuring. Not so much anymore. I just use the strict mock and declare expected behavior.
I've added a tweak to the MockFactory and MockInvocationHandler that allows you to switch a mock into debug mode, collecting all method calls/return values as they go through, regardless of mode or expectation. The generated stack trace can be accessed by the stackTrace() function in the MockInvocationHandler itself.
<cfset method = mf.createMock( "reflect.Method" ) />
<cfset test = createObject( "component", "test.Blank" ) />
<cfset other = createObject( "component", "sample.Collaborator" ) />
<cfset mf.expect( method.invokeMethod( test, structNew() ) ).andReturn( "Hello!" ) />
<cfset mf.expect( method.invokeMethod( other, structNew() ) ) />
<cfset mf.replay( method ) />
<cfset mf.debug( true, method ) />
<cfset method.invokeMethod( test, structNew() ) />
<cfset method.invokeMethod( other, structNew() ) />
<cfset mf.verify( method ) />
<cfdump var="#method.getProxyInvoker().stackTrace()#" />
I've also located and fixed the following issues:
- expects() was not triggering correctly due to the ResultMapper.add() not handling the first added request correctly.
- times() was overwriting the previous Result as well as the Range, instead of just modifying the previous Range.
- Component arguments were not compared at the name (aka type) level, which was allowing two of the same method call with different components to pass.