This section will mock the request and session scope beans with MockHttpServletRequest
and MockHttpSession
:
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>
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.
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; } }
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"; } }
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.
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:
WebApplicationContext
for our test by annotating the test class with @WebAppConfiguration
request
or session
into our test instance and prepared test data as appropriate, such as setting the request parameters and session attributesWebApplicationContext
via dependency injections, and asserted the values against the mocks18.116.21.152