Thursday, September 29, 2011

Different flavors of mocking with Groovy

If you don't use Groovy in your Java projects, you definitely should consider to start using it. There are many areas where Groovy would be very useful, but one I would like to talk a bit today is testing with mocking. There are a bunch of awesome frameworks to do mocking with Java (Mockito, powermock, EasyMock, ...) but Groovy allows you to do it out of the box, using built-in classes and language constructs.

Let's assume we have third-party service implementation to mock. If service was designed well, it implements some kind of interface (or interfaces) so clients could call different methods using interface contracts.
package com.example;

import java.util.Collection;

public interface SimpleService {
	Collection< String > getServiceProviders();
	Collection< String > getServiceProviders( final String regex );
}
The simplest and beautiful test case will look like this:
package com.example

import org.junit.Test

class SimpleServiceTestCase extends GroovyTestCase {
	@Test
	void testGetServiceProvidersByPattern() {
		// Create implementation from a map, method name : implementation (closure)
		def simpleService = [
			getServiceProviders : { String regex -> [ "Provider 1", "Provider 2" ] }  
		] as SimpleService
	
		assertEquals( [ "Provider 1", "Provider 2" ], 
			simpleService.getServiceProviders( "Provider*" ) )
	}
}
Awesome and easy! Let's consider another use case: service has implementation only, no interfaces. Could we mock and it as well? Yes!
package com.example;

public class SimpleServiceImpl {
	public Collection< String > getServiceProviders() {
		return null;
	}

	public Collection< String > getServiceProviders( final String regex ) {
		return null;
	}
}
The test case is a bit more verbose because of using Groovy mocking framework. You can also specify how many calls you expect as well as call sequences.
package com.example

import groovy.mock.interceptor.MockFor

import org.junit.Test

import com.example.impl.SimpleServiceImpl

class SimpleServiceTestCase extends GroovyTestCase {
	@Test
	void testGetServiceProviders() {
		def context = new MockFor( SimpleServiceImpl )
		
		context.demand.with {
			getServiceProviders() { -> [ "Provider 1", "Provider 2" ] }
		}
	
		context.use {
			def simpleService = new SimpleServiceImpl()
			
			assertEquals( [ "Provider 1", "Provider 2" ],
				simpleService.getServiceProviders() )
		}
	}
}
Cool and easy! The obvious question is, what about mocking static methods? You will love Groovy after that (as I do). Let's complicate our service a bit with static method.
package com.example;

public class SimpleServiceImpl {
	public static Collection< String > getDefaultServiceProviders() {
		return null;
	}
    
	// Other methods here
}
So the test case for mocking this static method is no more than one line of code (thanks to Groovy meta-programming capabilities):
package com.example

class SimpleServiceTestCase extends GroovyTestCase {
	@Test
	void testGetDefaultServiceProviders() {
		SimpleServiceImpl.metaClass.'static'.getDefaultServiceProviders = 
			{ -> [ "Provider 1", "Provider 2" ] } 
	
		assertEquals( [ "Provider 1", "Provider 2" ],
			SimpleServiceImpl.getDefaultServiceProviders() )		
	}
}
And that's it!