Creator of the Apache Tapestry web application framework and the Apache HiveMind dependency injection container. Howard has been an active member of the Java community since 1997. He specializes in all things Tapestry, including on-site Tapestry training and mentoring, but has lately been spreading out into fun new areas including functional programming (with Clojure), and NodeJS. Howard is a DZone MVB and is not an employee of DZone and has posted 81 posts at DZone. You can read more from them at their website. View Full User Profile

Yet More Spock Magic: Mocks

  • submit to reddit

Spock's built-in mock object capabilities are just a dream to use ... unlike other systems I've used, it doesn't get in your way, or force you to think backwards or inside out. Once again, some listings. These are for tests of Tapestry IoC's AspectDecorator service, which is used to create a wrapper interceptor around some other object. The test below shows how a supplied MethodAdvice callback object is invoked by the interceptor, if the advice is associated with the invoked method.

TestNG with EasyMock (Java)

public class AspectInterceptorBuilderImplTest extends IOCInternalTestCase
    private AspectDecorator decorator;

    public void setup()
        decorator = getService(AspectDecorator.class);

    public interface Subject
        void advised();

        void notAdvised();

    public void some_methods_not_intercepted() throws Exception
        Subject delegate = newMock(Subject.class)

        MethodAdvice advice = new MethodAdvice()
            public void advise(MethodInvocation invocation)
                assertEquals(invocation.getMethod().getName(), "advised");




        AspectInterceptorBuilder<Subject> builder = decorator.createBuilder(Subject.class, delegate, "<Subject>");

        builder.adviseMethod(Subject.class.getMethod("advised"), advice);

        Subject interceptor =;



Even this example is a bit streamlined, as some of the mock object capabilities, such as methods newMock(), replay() and verify() are being derived from the TestBase base class.


interface InterceptorSubject {

  void advised()

  void notAdvised()

class AspectInterceptorBuilderImplSpec extends AbstractSharedRegistrySpecification {

  private AspectDecorator decorator

  def setupSpec() {
    decorator = getService AspectDecorator

  def "ensure that non-advised methods are not passed through the MethodAdvice object"() {
    InterceptorSubject delegate = Mock()
    MethodAdvice advice = Mock()

    def builder = decorator.createBuilder(InterceptorSubject, delegate, "<InterceptorSubject>")

    builder.adviseMethod(InterceptorSubject.getMethod("advised"), advice)

    InterceptorSubject interceptor =




    1 * advice.advise(_) >> { MethodInvocation mi ->
      assert == "advised"
    1 * delegate.advised()
    0 * _




    1 * delegate.notAdvised()
    0 * _


Spock's wonderful when: / then: blocks organize the behavior into a stimulus followed by a response; using EasyMock, you have to train the mock objects for the response before introducing the stimulus (the method invocation). Further, with EasyMock there's one API for methods that return a fixed response, a second API for methods that throw an exception, and a third API for methods where the result must be calculated; in Spock the value after the >> operator is either a literal value, or a closure that can do what it likes, such as the one attached to MethodAdvice.advice() that checks for the expected method name, and then proceed()s to the delegate mock object's method.

I think that a reasonable developer, even without a thorough understanding of Spock, would get the gist of what this test does (perhaps with a little side note about the interaction system inside the then: block). On the other hand, I've seen when training people with TestNG and EasyMock that it very rarely sinks in immediately, if at all.





Published at DZone with permission of Howard Lewis Ship, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)