All these extensions simplify the dependency injections and transaction management of the operations under test.
Common Web Testing Scenarios
This section reviews some of the common scenarios for testing Web components and how you can use Spring's mock objects and the extensions to the JUnit framework in them.
Resolution to a Correct View
Producing the correct view based on input parameters is probably the most common function in operating a Web application. In the context of Spring MVC, this means that Spring MVC will return some ModelAndView object based on the state of the parameters.
You can test this function as a regular JUnit test by simply utilizing Mock objects as follows:
public void final testGettingToDetails throws Exception{
MyController myController = new MyController();
myController.setDetailsView( detailsViewName );
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
request.setMethod("POST");
request.addParameter("viewDetails", "true");
ModelAndView modelAndView = myController.handleRequest(request, response);
assertEquals("Incorrect view name", detailsViewName,
modelAndView.getViewName());
Since the controller will most likely utilize some service objects to decide on the resulting view, you could also supply a custom mock service object to the controller. For more details on utilizing custom objects, reference mockobjects.com.
Session-Related Operations
Another operation that is essential to any J2EE Web application is HttpSession-bound processing. For example, Spring MVC may need to determine whether an object is in the session and what its state is. Based on that, it would produce the correct result. You can test this scenario utilizing the MockHttpSession object and JUnit framework as follows:
public void testInvokesCorrectMethodWithSession() throws Exception {
TestController cont = new TestController();
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/invoiceView.app");
request.setSession(new MockHttpSession(null));
HttpServletResponse response = new MockHttpServletResponse();
ModelAndView mv = cont.handleRequest(request, response);
assertTrue("Invoked loggedIn method", cont.wasInvoked("loggedIn"));
assertTrue("view name is ",
mv.getViewName().equals("loggedIn"));
assertTrue("Only one method invoked", cont.getInvokedMethods() == 1);
//test the controller but without the session
request = new MockHttpServletRequest("GET", "/invoiceView.app");
response = new MockHttpServletResponse();
try {
cont.handleRequest(request, response);
fail("Should have rejected request without session");
}
catch (ServletException ex) {
//This is expected
}
}
Forwarding and Redirecting
An operation that a Spring MVC component performs can result in forwarding or redirecting to another URL. If your goal is to examine the resulting forward or redirect, you can test that scenario by examining the MockHttpResponse object and what is in its redirecting or forwarding value as follows:
String responseString = ((MockHttpServletResponse)httpResponse).getForwardedUrl();
assertEquals( "Did not forward to the expected URL", responseString, expectedString );
Producing the Correct Binary Output
How many times have you had to implement the "View as PDF" functionality? Below is a snippet of JUnit code that tests exactly that function utilizing mock output stream objects:
public void testPDFGeneration() throws Exception{
MockHttpServletRequest request = new MockHttpServletRequest();
MockHttpServletResponse response = new MockHttpServletResponse();
viewInvoiceAsPDFController.handleRequest( request, response );
byte[] responsePDFValues = response.getContentAsByteArray();
byte[] expectedPDFValues = loadBytesFromTestFile();
assertTrue( "Did not generate expected PDF content.",
Arrays.equals(
responsePDFValues,
expectedPDFValues ) );
}
Instead of returning the ModelAndView object, your controller ViewInvoiceAsPDFController produces binary output that you can capture as a binary array and evaluate for correctness.