Unit testing Spring Controller with Mockito or Groovy Spock

It is hard to overemphasize the role of unit testing in continuous delivery process. Unit tests help engineers reduce the number of bugs, hours spent on debugging, and contribute to healthier, more stable software. Unit tests are usually executed on developer computer before checking in into VCS and later during commit stage on Continuous Integration server.
Almost no code runs in isolation – it usually interact with different collaborators. But for purpose of unit testing we want to execute code under test in isolation.
We will stab calls to collaborators with predefined return values and check only code under test using test doubles. Test doubles helps us with following:

  • Isolate code unter test
  • Make test execute faster
  • Make execution deterministic
  • Simulate special condition

When we say we want to “isolate the code under test” we really mean to say that we’re isolating the code we want to test from all other code. In practice, “all other code” includes code that is invoked from the code we want to test.

Spring is one of the most popular web development framework and provides excellent testing support. But sometimes I found it easy to use other tools for testing as well. In this post we will be using couple of popular mocking frameworks to help us with the task of testing Spring controller. We will be using Groovy language as testing tool and compare two approaches: one with JUnit and java using mockito mocking framework and another one using Spock framework for Groovy.
For example, I have a simple controller under the test:

@Controller

public class InstitutionController {
    @Inject
    @Named("institutionService")
    private InstitutionService institutionService;
    
    @RequestMapping(value = "/institutions",method = RequestMethod.GET,
    headers = {"Accept=text/xml, application/json"})
    public @ResponseBody
    List <Institution> getShibbolethApprovedInstitutionList() {
        
        return institutionService.getShibbolethApprovedInstitutions();
    }
}

As you can see, our controller depends on institutionService that will be injected during Spring framework initialization via Spring dependency injection. There is not much controller code, but this is not the point. The point is to substitute call to institutionService with something that return predefined result so we can concentrate on testing only controllers code. Real institutionService method executes calls to a database, which we want to avoid during unit test. Mock object libraries such as JMock, Mockito and EasyMock are mature tools that programmer can yield a lot of power from. Each of these libraries have their own style of doing things but mostly you can do all the same stuff with any of these libraries. So let do first with Mockito:
public class InstitutionControllerTest {
	// create mock object
	@Mock
	InstitutionService institutionService;

	@Before
	public void setUp() throws Exception {
		// very important, Mock initialization
		MockitoAnnotations.initMocks(this);

	}

	@Test
	public void testGetShibbolethApprovedInstitutionList() {
		// create predefined return object - list of institutions
		LinkedList<Institution> mockedList = new LinkedList<Institution>();
		for (long i = 0; i < 10; i++) {
			Institution inst1 = new Institution(i);
			inst1.setIdp("http://myIDP" + i);
			inst1.setDisplayName("Test Name" + i);

			mockedList.add(inst1);
		}
		// create controller 
		InstitutionController controller = new InstitutionController();
		// substitute call to institutionService with predefined collaborator 
		given(institutionService.getShibbolethApprovedInstitutions())
				.willReturn(mockedList);
		
		ReflectionTestUtils.setField(controller, "institutionService",
				institutionService);

		// when - execute the controller
		List<Institution> result = controller
				.getShibbolethApprovedInstitutionList();

		// then
		assertEquals(10, result.size());
		assertEquals("http://myIDP0", result.get(0).getIdp());
		assertEquals("Test Name0", result.get(0).getDisplayName());

	}

}

Because we use Spring @Inject annotation I found it quite simple to replace call to collaborators with ReflectionTestUtils – a collection of reflection-based utility methods for use in unit and integration testing scenarios.
Now, lets do the same exercise using Groovy and Spock framework. This time we will do it in Behavior Driven Development (BDD) style, with given/when/then blocks. I found Groovy of partucular benefit for test-writing for Java (JVM) projects –

  • Less boilerplate syntax hiding the beef
  • More literal data structures
  • Additional methods for standard types
  • More powerful language constructs, such as Closures, list comprehension, native regular expressions, string interpolation, pattern matching, implicit type conversions.

One can write JUnit tests in Groovy, but I think Spock framework provide additional benefits with more declarative approach and build-in mocking capabilities and behavior style DSL. Here is the code:

class InstitutionaControllerSpec extends Specification {
// create mock for our service
	def institutionService=Mock(InstitutionService)
	
	def "Testing that controller returns correct list of institutions" () {
		
		
		given: 'List of predefined institutions objects' 
			List mockedList=[]
			Institution inst
			def log=0;
			(0L..9L).each { item -> 
						inst=new Institution(item) 						
						inst.setIdp("http://myIDP${item}")
						inst.setDisplayName("Test Name$item")
						
						mockedList.add(inst)
						inst=null;
			
			}
			assert mockedList.size()==10
			// tell the spoke that call to our function returns mockedList
			institutionService.getShibbolethApprovedInstitutions() >> mockedList
			
	when: "Calling controllers getShibbolethApprovedInstitutions() method"	
		 
		 InstitutionController controller=new InstitutionController();
		 // spring specific stabbing
		 ReflectionTestUtils.setField( controller, "institutionService", institutionService );
		 List result=controller.getShibbolethApprovedInstitutionList();
		
	then: "return list of approved institutions as list"
		result.size==10
		result[0].idp=='http://myIDP0'
		result[0].displayName=='Test Name0'
	}
}

Spock test can be executed from IDE as a regular JUnit test.
You have to make sure Groovy plugin in installed on Eclipse or IntelliJ.

Recent open source BDD frameworks such as Easyb and the Spock Framework present a more drastic step away from the traditional xUnit style of expressing desired behavior for our code. A lot of the time, however, that step is for the better.
Special thanks for some great ideas to the Lasse Koskela, author of the new book, Unit Testing in Java, available as MEAP from Manning publishing.
Getting started with Spock and Groovy

Spock and Mock Object Basics

Submit a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>