Mock Testing Spring MVC Controller

Filed under: development, spring, testing — Tags: , , , , , , — digitaljoel @ 2:08 pm

I’m in the midst of implementing a Spring MVC based web application. We have hudson for continuous integration builds that run all of our unit tests, but testing spring MVC controllers still just isn’t quite as easy as I would hope. There is some information on testing the controllers in the official spring documentation, but for someone like me that’s not a spring guru, or just starting out, it wasn’t enough to get me going. I recently was introduced to Mockito, so I spent a bit of time today trying to get a test for our controller using Mockito. It was simple and took no time at all.

I have yet to try it in a more complex controller method, but I think it’ll work just fine , especially when I get some utilities in place to initialize the mock objects that are commonly used by the controller. As it stands, here’s what I did to get it going. This tests the controller as a POJO, without using any spring configuration or capabilities.

Here is the controller I wish to test. Obviously I stripped out a bunch of code not needed for this demonstration.

@RequestMapping( "/admin/survey" )
public class SurveyAdminController
    private SurveyService surveyService;
    private UnitService unitService;
    private OrganizationService orgService;
     * Show the table of existing questions to the user
     * @param model
     * @return
    @RequestMapping( "questions" )
    public ModelAndView listQuestions()
        ModelAndView mav = new ModelAndView( "/admin/questionList");
        List<SurveyQuestion> questions = surveyService.findAllQuestions();
        mav.addObject( "questions", questions );
        List<UnitFeature> features = unitService.getAllFeatures();
        mav.addObject( "features", features );
        List<Organization> organizations = orgService.getAll();
        mav.addObject( "organizations", organizations );
        return mav;

For this simple test, it’s just going to validate that the view name is correct, and that the model that’s returned contains the correct information.


import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.List;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.web.servlet.ModelAndView;


public class SurveyAdminControllerTest
    @Mock SurveyService surveyService;
    @Mock UnitService unitService;
    @Mock OrganizationService orgService;
    @Mock MessageUtil messageUtil;

    public void setup()
        // this must be called for the @Mock annotations above to be processed.
        MockitoAnnotations.initMocks( this );
    public void testListQuestions()
        // setup our mock question list
        List<SurveyQuestion> questions = new ArrayList<SurveyQuestion>();
        questions.add( new SurveyQuestion( "asdf", null ));
        when( surveyService.findAllQuestions()).thenReturn( questions );

        // setup our mock feature list
        List<UnitFeature> features = new ArrayList<UnitFeature>();
        features.add( new UnitFeature( "TEST FEATURE" ));
        when( unitService.getAllFeatures()).thenReturn( features );

        // setup our mock organization list
        List<Organization> orgs = new ArrayList<Organization>();
        orgs.add( new Organization( "TEST ORGANIZATION" ));
        when( orgService.getAll()).thenReturn( orgs );

        // create an instance of the controller we want to test
        SurveyAdminController controller = new SurveyAdminController();

        // since we aren't using spring, these values won't be injected, so set them manually
        ReflectionTestUtils.setField( controller, "surveyService", surveyService );
        ReflectionTestUtils.setField( controller, "unitService", unitService );
        ReflectionTestUtils.setField( controller, "orgService", orgService );

        // call the method under test
        ModelAndView mav = controller.listQuestions();

        // review the results.
        assertEquals( questions, mav.getModel().get( "questions" ));
        assertEquals( features, mav.getModel().get( "features" ));
        assertEquals( orgs, mav.getModel().get( "organizations" ));
        assertEquals( "/admin/questionList", mav.getViewName());

The comments should be pretty self explanatory in the test class. The awesomeness of Mockito is how you setup the mocks. A line like this:

        when( unitService.getAllFeatures()).thenReturn( features );

reads very nicely and sets up the return value for my service object, which keeps me from needing a database or anything setup in order to test my controller method. Mockito ftw.


  1. Hi, I am trying to use mockito, to keep service class from using db. I am getting an error “Could not find field [as] on target [ebedynky.controllers.AdministratorController@1543cc88]

    Here is the code of test class

    public class AdministratorControllerTest {

    AdministratorController controller = new AdministratorController();
    AdministratorService as;

    * Test of getAdminZone method, of class AdministratorController.
    public void testGetAdminZone() {
    String expResult = "admin/adminZone";
    String result = controller.getAdminZone(new ExtendedModelMap());
    assertEquals(expResult, result);

    * Test of getNewRegistrations method, of class AdministratorController.
    public void testGetNewRegistrations() throws Exception {
    List users = new ArrayList();
    User user = new User();

    ReflectionTestUtils.setField(controller, "as", as);
    ModelAndView mav = controller.getNewRegistrations();


    and here’s the controller class

    public class AdministratorController {

    * Fetches the AdminZone page when requested.
    * @param model data holder for this view
    * @return string representing page location
    @RequestMapping(value = "/adminZone", method = RequestMethod.GET)
    public String getAdminZone(Model model) {
    return "admin/adminZone";

    * Fetches the NewRegistrations page when requested.
    * @return model and view representing page location and model
    @RequestMapping(value = "/newRegistrations", method = RequestMethod.GET)
    public ModelAndView getNewRegistrations() {
    AdministratorService as = new AdministratorService();
    Map model = new HashMap();
    model.put("users", as.getAllDenied());
    return new ModelAndView("user/allUsers", model);

    Comment by Milan Cernil — 2011/05/17 @ 6:27 am

  2. Oh, just a quick correction of question. I’ve just figured out, that I had needed to put AdministratorService as a global variable. But I have another problem. When I use assertEquals, I get null from getModel().get(users). The problem is obvious – even if I am using the mock objects, the hibernate still executes SQL query to db. Do you know where error/fault could be? Thank you very much

    Comment by Milan Cernil — 2011/05/17 @ 6:46 am

    • In your getNewRegistrations method you have the line
      AdministratorService as = new AdministratorService();
      so the controller is going to ignore the mocked one you setup in your test and just run the normal code path.

      Comment by digitaljoel — 2011/05/17 @ 9:13 am

  3. Hi Joel,

    Great example above, very insightful. I was wondering if you have used Mockito in concert with a Controller that needs something from the ApplicationContext. Does Mockito work in concert with the @ContextConfiguration annotation?

    Thanks, Tom

    Comment by Tom Hickerson — 2011/07/07 @ 10:09 am

    • Hi Tom,
      In the test above, since I’m testing the controller as a plain POJO, it’s not doing any spring configuration, including the context. But, you should be able to mock out any beans you need. As you can see, in my controller, all of the services are usually injected using the @Resource annotation. They are all spring beans that are loaded into the context. In the test, because the @Resource isn’t processed, I use the following to set it manually to my mocked out instance, where I’ve mocked the methods that I know will be called.

      // since we aren’t using spring, these values won’t be injected, so set them manually
      ReflectionTestUtils.setField( controller, “surveyService”, surveyService );
      ReflectionTestUtils.setField( controller, “unitService”, unitService );
      ReflectionTestUtils.setField( controller, “orgService”, orgService );

      Does that explanation help?

      Comment by digitaljoel — 2011/07/08 @ 10:30 am

  4. It’s very helpful to me. Thanks. :)

    Comment by 김제준 — 2011/08/22 @ 9:17 pm

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Silver is the New Black Theme. Blog at


Get every new post delivered to your Inbox.

Join 227 other followers