Testing Spring MVC

This section will mock the request and session scope beans with MockHttpServletRequest and MockHttpSession:

  1. Create a dynamic web project, SpringWebTest, add the Spring-mvc jars to the classpath, and modify the web.xml file (stored under <project>/WebContent/WEB-INF/) to enable Spring DispatcherServlet as follows:
    <?xml version="1.0" encoding="UTF-8"?>
    <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
      <display-name>SpringWebTest</display-name>
       <servlet>
        <servlet-name>dispatcher</servlet-name>
        <servlet-class>
          org.springframework.web.servlet.DispatcherServlet
        </servlet-class>
        <load-on-startup>1</load-on-startup>
      </servlet>
      <servlet-mapping>
        <servlet-name>dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
      </servlet-mapping>
      <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
          /WEB-INF/dispatcher-servlet.xml
        </param-value>
      </context-param>
    </web-app>
  2. Create a LoginService Java class in the com.packt.controller package to set the user ID and password and then validate them. The following is the class:
    public class LoginService {
      private String userId;
      private String password;
      //ignoring getters and setters for brevity
      public boolean isValid(){
        return getPassword().equals(getUserId());
      }
    }

    The isValid() method returns true when the username and password match.

  3. Create a LoginDetails class in the com.packt.controller package to store the user ID and the first login time. The following is the class:
      public class LoginDetails {
    
      private String user;
      private Date loginTime;
    
      public LoginDetails(String user, Date loginTime) {
        this.user = user;
        this.loginTime = loginTime;
      }
    
      public String getUser() {
        return user;
      }
    
      public Date getLoginTime() {
        return loginTime;
      }
    }
  4. Create a Controller class to handle requests. We'll have three requests: the initial request "/" will load the login page, the login page submit will invoke the "/onLogin" request, and validate the user ID and password. If the login is invalid, route the user to the login page; otherwise, store the user ID and login time in the session and pass the request to the greetings page. On the greetings page, the user can click on the Login details hyperlink to view the login time and user ID, and this will generate a "/onLoginDetail" request and get the login details from the session. The controller will be dependent on LoginService to get the user ID and password from the request and validate them, and on LoginDetails to fetch the user ID and login time from the session. The following is the controller:
    @Controller
    @Scope("session")
    public class LoginController implements Serializable {
      @Autowired
      private LoginService loginService;
    
      @Autowired
      private LoginDetails loginDetails;
    
      @RequestMapping({ "/", "/login" })
      public String onStartUp(ModelMap model) {
        return "login";
      }
    
      @RequestMapping({ "/onLogin" })
      public ModelAndView onLogin(ModelMap model, HttpSession 
            session, HttpServletRequest request) {
        if (!loginService.isValid()) {
          model.addAttribute("error", "Invalid user 
              name and password");
          return new ModelAndView("login", model);
        }
    
        session.setAttribute("loggedInTime", new Date());
        session.setAttribute("userId", 
              request.getParameter("userId"));
        
        model.addAttribute("name", "Welcome reader!");
        return new ModelAndView("greetings", model);
      }
    
      @RequestMapping({ "/onLoginDetail" })
      public String onLoginDetail(ModelMap model) {
        model.addAttribute("name", 
              loginDetails.getUser());
        model.addAttribute("time", 
              loginDetails.getLoginTime());
        return "greetings";
      }
    
    }
  5. Add an application context, dispatcher-servlet.xml, to define the beans. The loginService bean is defined in the request scope, and its properties are set from the request parameters using the p namespace. The loginDetails bean is defined in the session scope, and its constructor arguments are set from the session attributes using the c namespace:
    <bean id="loginService" 
            class="com.packt.controller.LoginService"
        scope="request" 
            p:userId="#{request.getParameter('userId')}"
        p:password="#{request.getParameter('password')}">
        <aop:scoped-proxy />
    </bean>

    The <aop:scoped-proxy> is used to expand the scope of the beans:

      <bean id="loginDetails" 
            class="com.packt.controller.LoginDetails"
        c:user="#{session.getAttribute('userId')}" 
          c:loginTime="#{session.getAttribute('loggedInTime')}"
        scope="session">
        <aop:scoped-proxy />
      </bean>
    
      <context:component-scan base-package="com.packt" />
      <bean
      class="org.springframework.web.servlet.view.
            InternalResourceViewResolver">
        <property name="prefix">
          <value>/WEB-INF/pages/</value>
        </property>
        <property name="suffix">
          <value>.jsp</value>
        </property>
      </bean>

    Also, the view resolver tells the Spring container to resolve the views from the /WEB-INF/pages folder with the .jsp suffix. This means that if the controller returns a view named greetings, then resolve the logical view to a physical greetings.jsp page under the /WEB-INF/pages folder.

  6. How can we get the session and request scope beans in our JUnit test and set the request and session attributes? The following test class autowires the request-scoped LoginService and session-scoped LoginDetails; it also verifies the logic that isValid() checks the username and password, and the session attributes are properly passed to LoginDetails:
    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations ="classpath:beans.xml")
    @WebAppConfiguration
    public class LoginControllerTest {
      @Autowired
      private LoginService loginService;
      @Autowired
      private LoginDetails loginDetails;
      @Autowired MockHttpServletRequest request;
      @Autowired MockHttpSession session;
    
      @Test
      public void requestScope() throws Exception {
        request.setParameter("userId", "rock");
            request.setParameter("password", "rock");
            
            assertTrue(loginService.isValid());
      }
      
      @Test
      public void sessionScope() throws Exception {
         Date now = new Date();
         session.setAttribute("userId", "john");
         session.setAttribute("loggedInTime", now);
            
         assertEquals("john",loginDetails.getUser());
         assertEquals(now,loginDetails.getLoginTime());
      }
    }

The following things took place in the preceding test:

  • We loaded a WebApplicationContext for our test by annotating the test class with @WebAppConfiguration
  • We injected the mock request or session into our test instance and prepared test data as appropriate, such as setting the request parameters and session attributes
  • We invoked the web component from the configured WebApplicationContext via dependency injections, and asserted the values against the mocks
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.21.152