Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Simplify Unit Testing for Spring Web Components : Page 2

Utilize Spring mock objects and Spring's extensions to the JUnit framework to simplify unit testing for Spring Web components.




Application Security Testing: An Integral Part of DevOps

Spring-Specific Extensions to the JUnit Framework

Spring provides the following set of Spring-specific extensions to the JUnit framework:
  • AbstractDependencyInjectionSpringContextTests – This is a superclass for tests, depending on the Spring context.
  • AbstractSpringContextTests – This is a superclass for all JUnit test cases using a Spring context, and as such, it is not intended to be used directly. You will most likely end up using either AbstractDependencyInjectionSpringContextTests or subclasses of AbstractTransactionalSpringContextTests.
  • AbstractTransactionalSpringContextTests – This is a superclass for all the tests that should occur in a transaction but that will normally roll the transaction back upon the completion of each test. You need to override onSetUpInTransaction and onTearDownInTransaction to manually initiate and/or commit the transaction (for instance, to flush the Hibernate session).
  • AbstractTransactionalDataSourceSpringContextTests – This is a subclass of AbstractTransactionalSpringContextTests that is geared towards the use of the Spring's JDBC-based jdbcTemplate convenience class.

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.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



We have made updates to our Privacy Policy to reflect the implementation of the General Data Protection Regulation.
Thanks for your registration, follow us on our social networks to keep up-to-date