Monday, September 6, 2010

Spring: Using Mock Objects For Unit Testing MVC Controllers

Spring has a nice framework to unit test controller for web/rest applications and it integrates nicely with Junit.Assuming that you wrote a CustomerController for handling REST requests to create a customer. A basic CustomerController looks like this:

@Controller
@RequestMapping("/customers")
public class CustomerController {


@RequestMapping (method = RequestMethod.POST)
public void createCustomer(HttpServletRequest request,
                  HttpServletResponse response) {
//your code here
}
}


Now to test this controller using Spring Mock objects, the basic steps are as follows in your unit test:

Step1: Declare that you want to run test using JUnit. For example to run test using JUnit4 you need to use @RunWith annotation as follows:

@RunWith(SpringJUnit4ClassRunner.class)
public class CustomerControllerTest extends TestCase {

@Test
public void testCreateCustomer() throws Exception {
}

}


Step2: Specify the spring bean configuration using @ContextConfiguration so that Controller works from unit test.



@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/customer/rest-config.xml")
public class CustomerControllerTest extends TestCase {

@Test
public void testCreateCustomer() throws Exception {
}

}


Step3: Setup DispatcherServlet. DispatchServlet will be used to send mock request to the controller. Setting up DispatchServlet requires implementing ApplicationContextAware.


@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/customer/rest-config.xml")
public class CustomerControllerTest extends TestCase implements ApplicationContextAware {

private Servlet servlet;
 private ApplicationContext applicationContext;

@SuppressWarnings("serial")
@Before
private void init() {
servlet = new DispatcherServlet() {

@Override
protected WebApplicationContext createWebApplicationContext(
WebApplicationContext parent) throws BeansException {
GenericWebApplicationContext genericContext = new GenericWebApplicationContext();
genericContext.setParent(applicationContext);
genericContext.refresh();
return genericContext;
}

};
}

@Test
public void testCreateCustomer() throws Exception {
}

public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
this.applicationContext = arg0;
}

}


Step4: Finally use MockHttpServletRequest to build the request, send it and process the response.




@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:spring/customer/rest-config.xml")
public class CustomerControllerTest extends TestCase implements ApplicationContextAware {

private Servlet servlet;
private ApplicationContext applicationContext;

@SuppressWarnings("serial")
@Before
private void init() {
servlet = new DispatcherServlet() {

@Override
protected WebApplicationContext createWebApplicationContext(
WebApplicationContext parent) throws BeansException {
GenericWebApplicationContext genericContext = new GenericWebApplicationContext();
genericContext.setParent(applicationContext);
genericContext.refresh();
return genericContext;
}

};
}

@Test
public void testCreateCustomer() throws Exception {
MockHttpServletRequest request = new MockHttpServletRequest();
// set uri, request parameter, request body, omitted here
MockHttpServletResponse response = new MockHttpServletResponse();

// send the request
MockServletConfig servletConfig = new MockServletConfig();
servlet.init(servletConfig);
servlet.service(request, response);

// validate response
String responseContent = response.getContentAsString();
int responseCode = response.getStatus();

}

public void setApplicationContext(ApplicationContext arg0)
throws BeansException {
this.applicationContext = arg0;
}

}
Promote your blog

No comments:

Post a Comment