Loading...

January 25, 2010

Groovy Goodness: Create Stubs for Testing

We can write unit tests with Groovy by simply extending the GroovyTestCase class. In the test we can use the default Groovy classes MockFor and StubFor to create mocks and stubs for classes and interfaces. We can create a mock or stub for Groovy classes, but also for Java classes. Once we have a mock or stub we can execute the code we want to test in the context of the mock or stub with the use() method.

In this example we create a stub for a Groovy service class. We want to define our own return result for the method findLanguages(), so we can test the logic in the caller class.

import groovy.mock.interceptor.*

class CallServiceTest extends GroovyTestCase {
    def callService = new CallService()
    
    void testServiceCall() {
        def stub = new StubFor(MyService.class)
        stub.demand.findLanguages { ['Java', 'Groovy'] }  // Return one language with an 'a' and one without.
        stub.use {
            callService.myService = new MyService()
            def result = callService.findLanguagesWithA()  // Will use method from stub.
            assert 1 == result.size()
            assert 'Java' == result[0]
        }
    }
    
    void testEmptyResult() {
        def stub = new StubFor(MyService.class)
        stub.demand.findLanguages { ['Groovy', 'Clojure'] }  // Return no languages with an 'a'.
        stub.use {
            callService.myService = new MyService()
            def result = callService.findLanguagesWithA()  // Method from stub is invoked.
            assert !result
        }
    }
}

class CallService {
    def myService = new MyService()
    
    List findLanguagesWithA() {
        def languages = myService.findLanguages()
        languages.grep({ it.contains('a') })
    }
}
class MyService {
    List findLanguages() {
        // Get real data from database for example.
        // That is why we want to stub this class, so we don't rely on
        // the database.
        []
    }
}