Thursday, December 19, 2013

Spring MVC: Apply Mockito Framework at Controller.

Hi !!! Today, i have a new post. How to apply Mockito Framework for Spring MVC at Controller layer.

What is Mockito?
Mockito is a mocking framework that tastes really good. It lets you write beautiful tests with clean & simple API. Mockito doesn't give you hangover because the tests are very readable and they produce clean verification errors: Read more https://code.google.com/p/mockito/

I) Add Mockito Maven Dependency:         
II) Controller Layer:
package com.fpt.controller;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.fpt.domain.Person;
import com.fpt.service.PersonService;

@Controller
public class RestController {
    protected static Logger logger = Logger.getLogger(RestController.class);

    @Autowired
    private PersonService personService;

    // http://localhost:8080/spring-mvc-mokito/mvc/all/persons

    @RequestMapping(value = "/all/persons", method = RequestMethod.GET, headers = "Accept=application/xml, application/json")

    public String getAllPerson(ModelMap model) {
        logger.debug("Provider has received request to get all persons");
        List result = personService.getAllPerson();
        model.addAttribute("model_get_all_person", result);
        return "get_all_person";
    }
}

III) Unit test for Controller layer applying Mockito:
package com.fpt.controller.test;

import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.model;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.view;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.fpt.controller.RestController;
import com.fpt.domain.Person;
import com.fpt.service.PersonService;


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigContextLoader.class)
public class RestControllerAnnoTest {

    @Configuration
    static class ContextConfiguration {

        @Bean
        public PersonService personService() {
            return Mockito.mock(PersonService.class);
        }

        @Bean
        public RestController loginController() {
            return new RestController();
        }
    }

    @Autowired
    private RestController restController;

    @Autowired
    private PersonService personService;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(this.restController).build();
    }

    @After
    public void teardown() {
        mockMvc = null;
    }

    @Test
    public void testGetAllPerson() throws Exception {
        Person p1 = new Person();
        p1.setFirstName("firstName01");
        p1.setLastName("lastName01");
        p1.setId(123l);
        p1.setMoney(321d);

        Person p2 = new Person();
        p2.setFirstName("firstName02");
        p2.setLastName("lastName02");
        p2.setId(123l);
        p2.setMoney(321d);

        List expectedPeople = new ArrayList();
        expectedPeople.add(p1);
        expectedPeople.add(p2);

        when(personService.getAllPerson()).thenReturn(expectedPeople);

        this.mockMvc
                .perform(get("/all/persons"))
                .andExpect(status().isOk())
                .andExpect(
                        model().attribute("model_get_all_person",
                                expectedPeople))
                .andExpect(view().name("get_all_person"));
        ;
    }
}

IV) Create a new file ApplicationContent_Test.xml at src/test/resources:
 
V) Unit test for Controller layer without Mockito:
package com.fpt.controller.test;

import static org.junit.Assert.assertEquals;
import java.util.List;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.ui.ModelMap;
import com.fpt.controller.RestController;
import com.fpt.domain.Person;
import com.fpt.service.PersonService;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "/applicationContext_TEST.xml" })
public class RestControllerXmlTest {

    @Autowired
    private RestController restController;

    @Autowired
    private PersonService personService;

    @Test
    public void testGetAllPerson() throws Exception {
        Person p1 = new Person();
        p1.setFirstName("firstName01");
        p1.setLastName("lastName01");
        p1.setId(123l);
        p1.setMoney(321d);

        Person p2 = new Person();
        p2.setFirstName("firstName02");
        p2.setLastName("lastName02");
        p2.setId(123l);
        p2.setMoney(321d);

        List expectedPeople = personService.getAllPerson();
        expectedPeople.add(p1);
        expectedPeople.add(p2);

        ModelMap modelMap = new ModelMap();
        String viewName = restController.getAllPerson(modelMap);
        assertEquals("get_all_person", viewName);

        @SuppressWarnings("unchecked")
        List listPersons = (List) modelMap             .get("model_get_all_person");


        assertEquals("There are 2 objects",2, listPersons.size());     
        assertEquals("firstName01", listPersons.get(0).getFirstName());
        assertEquals(Long.valueOf(123), listPersons.get(0).getId());
        assertEquals("lastName01", listPersons.get(0).getLastName());
        assertEquals(Double.valueOf(321.0), listPersons.get(0).getMoney());
    }
}

Source Code