Thursday, February 28, 2008

A small Gotcha using Groovy's StubFor or MockFor

I (literally) just posted about my first experience with Groovy. I forgot to mention one thing that I got hung up on when using the StubFor class (this applies to MockFor as well).

I have a simple utility method that just reads from a file and returns the text. I wrote the following unit test and it looked like this at first.

1. def void testReadFromFile() {
2. def expectedText = "<test>myXml</test>"
3. def fileStub = new StubFor(File)
4. fileStub.demand.text {
5. return expectedText
6. }
8. fileStub.use {
9. def val = FileIO.readFromFile("x.xml")
10. println("val: " + val)
11. assertEquals("Expected Text not Found", expectedText, val)
12. }
13. }

Do you see anything wrong here? Check out line 4. Still think it looks ok? The problem is that there is no method "text". There is however, a method "getText()". That's right. Even though the code I'm testing looks like this

   new File(fileName).text

and works perfectly fine, under the covers the actually method being called is getText(). Running the unit test from above results in the following error:

   junit.framework.AssertionFailedError: No more calls to 'getText' expected at this point. End of demands.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(
at java.lang.reflect.Constructor.newInstance(
at org.codehaus.groovy.runtime.MetaClassHelper.doConstructorInvoke(
at groovy.lang.MetaClassImpl.doConstructorInvoke(
at groovy.lang.MetaClassImpl.invokeConstructor(
at groovy.lang.MetaClassImpl.invokeConstructor(

Line 4 in the unit test above should read like this:

4. fileStub.demand.getText {

So, remember that when using StubFor or MockFor your demands must specify the actual method that will be called.

No comments: