[ Team LiB ] |
7.7 Submitting Form Data7.7.1 ProblemYou want to verify that your servlet correctly handles form parameters. 7.7.2 SolutionWrite a ServletTestCase to simulate passing valid and invalid form parameters to a servlet.
7.7.3 DiscussionMost web applications have some sort of user input. A good example is a page for new customers to create an account. The page might ask for name, address, age, and gender. In the web world, this calls for an HTML form containing one or more input elements to solicit information from a user. The information contained in the input elements is added to the HTTP request by the browser when the user submits the form. As a servlet programmer, you must process each parameter and ensure that invalid information does not cause the servlet to crash or, even worse, corrupt a data store. Start this recipe by looking at an example HTML form that is submitted to a servlet:[8]
<form method="post" action="LoginServlet"> <table border="1"> <tr> <td>Username:</td> <td><input type="text" name="username"/></td> </tr> <tr> <td>Password:</td> <td><input type="password" name="password"/></td> </tr> <tr> <td colspan="2" align="center" > <input type="submit" name="submit" value="Login"/> </td> </tr> </table> </form> When forms are submitted, the browser automatically adds each form field to the outgoing request. In the example above, the form data is sent to a servlet mapped to the name LoginServlet. The LoginServlet retrieves, verifies, and processes the data, which in this case is intended to authenticate a user. Example 7-1 shows the first iteration of the servlet. Example 7-1. First iteration of the LoginServletpackage com.oreilly.javaxp.cactus.servlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.ServletException; import java.io.IOException; public class LoginServlet extends HttpServlet { /** * Cactus does not automatically invoke this method. If you want to * test this method then your test method must explicitly invoke it. */ protected void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException { if (!validateParameters(req)) { req.setAttribute("errorMessage", "Please enter your username and password"); req.getRequestDispatcher("/login.jsp").forward(req, res); return; } // authenticate user } protected boolean validateParameters(HttpServletRequest req) { // @todo - implement this! return false; } } Our servlet overrides the doPost( ) method and immediately calls the validateParameters( ) method, which is the method we are going to test. First, we make the test fail, and then write the code to make it pass. Example 7-2 shows the next iteration of the Cactus test. Example 7-2. Second iteration of the LoginServlet testpackage com.oreilly.javaxp.cactus.servlet; import org.apache.cactus.ServletTestCase; import org.apache.cactus.WebRequest; public class TestLoginServlet extends ServletTestCase { private LoginServlet servlet; public TestLoginServlet(String name) { super(name); } public void setUp( ) { this.servlet = new LoginServlet( ); } public void beginValidFormParameters(WebRequest webRequest) { webRequest.addParameter("username", "coyner_b", WebRequest.POST_METHOD); webRequest.addParameter("password", "secret", WebRequest.POST_METHOD); } public void testValidFormParameters( ) { assertTrue("Valid Parameters.", this.servlet.validateParameters(this.request)); } } The test method testValidFormParameters( ) fails because our servlet is hardcoded to return false. Now that we have seen our test fail, let's update the validateParameters( ) method to make our test pass. Example 7-3 shows the new and improved servlet code. Example 7-3. Updated servletprotected boolean validateParameters(HttpServletRequest req) { String username = req.getParameter("username"); String password = req.getParameter("password"); if ((username == null || "".equals(username)) || (password == null || "".equals(password))) { return false; } else { return true; } } Servlets must always check request parameters for null and an empty string. A parameter is null if the parameter does not exist in the request. A parameter contains an empty string when the parameter exists without a value. Example 7-4 shows how to test for these conditions. Example 7-4. Improved unit testpackage com.oreilly.javaxp.cactus.servlet; import org.apache.cactus.ServletTestCase; import org.apache.cactus.WebRequest; public class UnitTestLoginServlet extends ServletTestCase { private LoginServlet servlet; public TestLoginServlet(String name) { super(name); } public void setUp( ) { this.servlet = new LoginServlet( ); } public void beginValidFormParameters(WebRequest webRequest) { webRequest.addParameter("username", "coyner_b", WebRequest.POST_METHOD); webRequest.addParameter("password", "secret", WebRequest.POST_METHOD); } public void testValidFormParameters( ) { assertTrue("Valid Parameters.", this.servlet.validateParameters(this.request)); } public void beginUsernameParameterNull(WebRequest webRequest) { webRequest.addParameter("password", "secret", WebRequest.POST_METHOD); } public void testUsernameParameterNull( ) { assertTrue("Username form field not specified in request.", !this.servlet.validateParameters(this.request)); } public void beginUsernameParameterEmptyString(WebRequest webRequest) { webRequest.addParameter("username", "", WebRequest.POST_METHOD); webRequest.addParameter("password", "secret", WebRequest.POST_METHOD); } public void testUsernameParameterEmptyString( ) { assertTrue("Username not entered.", !this.servlet.validateParameters(this.request)); } public void beginPasswordParameterNull(WebRequest webRequest) { webRequest.addParameter("username", "coyner_b", WebRequest.POST_METHOD); } public void testPasswordParameterNull( ) { assertTrue("Passord form field not specified in request.", !this.servlet.validateParameters(this.request)); } public void beginPasswordParameterEmptyString(WebRequest webRequest) { webRequest.addParameter("username", "coyner_b", WebRequest.POST_METHOD); webRequest.addParameter("password", "", WebRequest.POST_METHOD); } public void testPasswordParameterEmptyString( ) { assertTrue("Password not entered.", !this.servlet.validateParameters(this.request)); } } 7.7.4 See AlsoChapter 5 provides an alternate tool for testing server side code. Chapter 6 provides a discussion on mock objects. |
[ Team LiB ] |