Search code examples
unit-testinggroovyclosuresexpandoexpandometaclass

In Groovy, When Does It Makes Sense To Use An Expando vs the 'as' operator and Closures?


Groovy is a wonderful language that offers lots of different choices.

In thinking about unit tests, when does it make sense to use an Expando object vs. the "as" operator with closures?

http://groovy.codehaus.org/Developer+Testing+using+Maps+and+Expandos+instead+of+Mocks vs http://groovy.codehaus.org/Developer+Testing+using+Closures+instead+of+Mocks

For simple cases, their use seems so similar.

Thanks!


Solution

  • As noted on the page you referenced regarding using Closures instead of mocks, by themselves they only work for mocking interfaces and only if that interface has a single method. So if the class under test is not using an interface or you need to mock more than a single method you need to use either an Expando or Map. I prefer to be consistent and always use a Map, the code I deal with rarely needs objects mocked with a single interface method and using a Map does not require that many more keystrokes.

    interface Foo {
        def someMethod(s)
    }
    
    // Closure, this breaks if someOtherMethod() is added to Foo or if Foo is a class
    def mockMethod = { arg -> ...}
    def myTestObject = new ObjectUnderTest(mockMetod as Foo)
    
    // Map
    def mockMethod = { arg -> ...}
    def myTestObject = new ObjectUnderTest([someMethod:mockMethod] as Foo)
    

    Not sure there is a significant difference between using a Map or Expando to mock an object, but I prefer a Map just because of the nice way you can declare a Map literal and not have to new up an Expando.