Skip to: Site menu | Main content

Groovy 

      Download | Documentation | Developers | Community

An agile dynamic language for the Java Platform

Using MockFor and StubFor Add comment to Wiki View in Wiki Edit Wiki page Printable Version

Groovy Mocks

Mock objects are used to assist (typically unit) testing of classes in isolation.

The Groovy Mock resides in the groovy.mock.interceptor package. It is an all-groovy mock testing library.

In principle, it is used like this:

import groovy.mock.interceptor.MockFor

def mocker = new MockFor(Collaborator.class)  // create the Mock support
mocker.demand.one(1..2) { 1 }                 // demand the 'one' method one or two times, returning 1
mocker.demand.two()     { 2 }                 // demand the 'two' method exactly once, returning 2
mocker.use {                                  // start using the Mock
    def caller = new Caller()                 // caller will call Collaborator
    assertEquals 1, caller.collaborateOne()   // will call Collaborator.one
    assertEquals 1, caller.collaborateOne()   // will call Collaborator.one
    assertEquals 2, caller.collaborateTwo()   // will call Collaborator.two
}                                             // implicit verify for strict expectation here

Groovy Mocks were inspired by EasyMock.

Find background information about Mocks and endo-testing under XP2000 conference paper.

For an extended example, see Using Testing Frameworks with Groovy

Features

  • typical mock style of failing early
  • mocks instance and class methods
  • mocks final methods and final Collaborators
  • mocks Groovy and Java Collaborators (but Caller must be groovy)
  • can mock all objects of a given class (or a single Groovy object)
  • mocks even if Collaborator cannot be injected into the Caller
  • mocks even if Collaborator is not accessible on the Caller (no getter)
  • demanded calls specified via recording calls on the Demand object (EasyMock style).
  • cardinality specified as Ranges, default is 1..1; 'optional' can be achieved with 0..1
  • behavior specified via Closures, allowing static or calculated return values, throwing exceptions, asserting argument values, etc. (even tricky sequence constraints by sharing state in the testMethod scope between the behavior Closures)
  • matching parameter list specified via Closure's parameter list, supporting typed or untyped params, default params, and varargs.
  • not dependent on any external mock library

For an extensive list of usages see the unit tests that show how to use the mock package.

MockFor Tests

Some tests to demonstrate how to use the MockFor class

import grails.test.*
import groovy.mock.interceptor.*

class MockForTests extends GrailsUnitTestCase
{
    void test_mock_single_method_and_use_as_category()
    {
        def mock = new MockFor(MockForTestsClass)
        mock.demand.amethod { "from mock"}
        mock.use {
        	assertEquals "from mock", new MockForTestsClass().amethod()
        }
    }
    
    /**
     * TODO mocking static methods doesnt seem to work
     */
    void DISABLED_test_mock_single_static_method_and_use_as_category()
    {
        def mock = new MockFor(MockForTestsClass)
        mock.demand.static.astaticmethod { "from static mock"}
        mock.use {
        	assertEquals "from static mock", new MockForTestsClass().amethod()
        }
    }
    
    void test_mock_single_method_and_use_proxy()
    {
        def mock = new MockFor(MockForTestsClass)
        mock.demand.amethod { "from mock with proxy"}
        
        def proxy = mock.proxyInstance()
        assertEquals "from mock with proxy", proxy.amethod()
        mock.verify proxy
    }
    
    void test_stub_single_method()
    {
        def mock = new StubFor(MockForTestsClass)
        mock.demand.amethod { "from stub" }
        mock.use { 
        	assertEquals "from stub", new MockForTestsClass().amethod()
        }
    }
    
    void test_stub_single_method_and_expect_no_errors()
    {
        def mock = new StubFor(MockForTestsClass)
        mock.demand.amethod { "not called" }
        mock.use {
        	new MockForTestsClass()
        }
    }
    
    void test_mock_method_with_parameters()
    {
        def mock = new MockFor(MockForTestsClass)
        mock.demand.amethodwithparameters { a -> "from mock with parameters ${a}" }
        
        mock.use { 
        	assertEquals "from mock with parameters 123",  
        		new MockForTestsClass().amethodwithparameters(123)
        }
    }
}

class MockForTestsClass
{
    void amethod()
    {
        println "original method"
    }
    
    static void astaticmethod()
    {
        println "original static method"
    }
    
    void amethodwithparameters(message)
    {
        println "original method with parameters"
    }
}