tdd:测试驱动WEB组件

相信大家有好多人会使用JUNIT进行单元测试了,但是在WEB开发中仅仅对MVC设计模式中业务逻辑进行测试还是远远不够的,如何对 控制器视图层进行单元测试将是本文的重点:

 

主要分享的内容:

 

一.测试驱动 Java  Servlet

二.测试驱动 Spring 控制器

三.用JspTest 测试驱动JSP

 

开始吧。

 

一.测试驱动 Java  Servlet

servlet通常会有一两个公有方法,每个公有方法处理一种类型的HTTP请求,例如:GET,POST,HEAD,PUT等。每个方法都以doXXX格式命名。大部分情况下都只处理GET和POST请求而已。基类javax.servlet.http.HttpServlet的service方法负责处理所有HTTP请求,其会根据HTTP请求类型把请求转发到对应的doXXX方法上。

 

doXXX方法的第一个参数HttpServletRequest封装了HTTP请求,其包含请求相关参数,HTTP头及其他信息。

第二个参数HttpServletResponse主要用于给客户端回送应答。任何发给浏览器的HTTP头都可以放到应答对象中。所有想输出的内容都可以转给应答中的printWriter对象和ServletOutputStream对象。

 

实例:

1.模拟请求和应答

 

	package com.tddinaction.j2ee.web.controller.servlet;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Enumeration;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class EchoServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request,
            HttpServletResponse response) throws ServletException,
            IOException {
        PrintWriter writer = response.getWriter();
        for (Enumeration e = request.getParameterNames(); e.hasMoreElements(); ) {
            String parameter = String.valueOf(e.nextElement());
            String[] values = request.getParameterValues(parameter);
            for (int i = 0; i < values.length; i++) {
                writer.write(parameter + "=" + values[i]);
                writer.write("\n");
            }
        }
        writer.close();
    }
}


package com.tddinaction.j2ee.web.controller.servlet;

import junit.framework.TestCase;

import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class EchoServletTest extends TestCase {

	@Test
	public void testEchoingParametersWithMultipleValues() throws Exception {
		//通过第三方的测试替身来模拟请求对象和应答对象。用来模拟浏览器发起的请求
		MockHttpServletRequest request = new MockHttpServletRequest();
		MockHttpServletResponse response = new MockHttpServletResponse();

		request.addParameter("param1", "param1value1");
		request.addParameter("param2", "param2value1");
		request.addParameter("param2", "param2value2");
		new EchoServlet().doGet(request, response);
		String[] lines = response.getContentAsString().split("\n");
		assertEquals("Expected as many lines as we have parameter values", 3, lines.length);
		assertEquals("param1=param1value1", lines[0]);
		assertEquals("param2=param2value1", lines[1]);
		assertEquals("param2=param2value2", lines[2]);
	}
}

 

 2.测试重定向

 

package com.tddinaction.j2ee.web.controller.servlet;

import java.io.IOException;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class LoginServlet extends HttpServlet {

	@Override
	protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		String user = request.getParameter("j_username");
		String pass = request.getParameter("j_password");
		if (isValidLogin(user, pass)) {
			request.getSession().setAttribute("username", user);
			response.sendRedirect("/frontpage");
		} else {
			forwardTo("/invalidlogin", request, response);
		}
	}

	private boolean isValidLogin(String user, String pass) {
		if (pass.equals("correctpassword")) {
			return true;
		} else if (pass.equals("wrongpassword")) {
			return false;
		}
		return false;
	}

	private void forwardTo(String path, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
		RequestDispatcher dispatcher = request.getRequestDispatcher(path);
		dispatcher.forward(request, response);
	}
}


package com.tddinaction.j2ee.web.controller.servlet;

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;

public class TestLoginServlet {

	private static final String VALID_USERNAME = "validuser";

	private LoginServlet servlet;

	private MockHttpServletRequest request;

	private MockHttpServletResponse response;

	@Before
	public void setUp() {
		servlet = new LoginServlet();
		request = new MockHttpServletRequest();
		response = new MockHttpServletResponse();
	}

	@Test
	public void wrongPasswordShouldRedirectToErrorPage() throws Exception {
		request.addParameter("j_username", VALID_USERNAME);
		request.addParameter("j_password", "wrongpassword");
		servlet.service(request, response);
		assertUserEndedUpOnPage("/invalidlogin");
	}

	@Test
	public void validLoginForwardsToFrontPageAndStoresUsername() throws Exception {
		request.addParameter("j_username", VALID_USERNAME);
		request.addParameter("j_password", "correctpassword");
		servlet.service(request, response);
		assertUserEndedUpOnPage("/frontpage");
		assertEquals(VALID_USERNAME, request.getSession().getAttribute("username"));
	}

	private void assertUserEndedUpOnPage(String expected) {
		String actual = response.getRedirectedUrl();
		if (actual == null) {
			actual = response.getForwardedUrl();
		}
		assertEquals(expected, actual);
	}
}

 

 

二.测试驱动 Spring 控制器

 

 1.失败的登录:

 

package com.tddinaction.j2ee.web.controller.spring;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import com.tddinaction.j2ee.web.controller.authenticator.Authenticator;

public class LoginController implements Controller {

    private Authenticator authenticator;

    public void setAuthenticator(Authenticator authenticator) {
        this.authenticator = authenticator;
    }

    public ModelAndView handleRequest(HttpServletRequest request,
            HttpServletResponse response) throws Exception {
        String user = request.getParameter("j_username");
        String pass = request.getParameter("j_password");
        if (authenticator.isValidLogin(user, pass)) {
            return new ModelAndView("frontpage");
        }
        return new ModelAndView("wrongpassword");
    }
}


package com.tddinaction.j2ee.web.controller.spring;

import static org.junit.Assert.assertEquals;

import org.junit.Before;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.ModelAndView;

import com.tddinaction.j2ee.web.controller.authenticator.MockAuthenticator;

public class TestLoginController {

	private static final String CORRECT_PASSWORD = "correctpassword";

	private static final String VALID_USERNAME = "validuser";

	private MockHttpServletRequest request;

	private MockHttpServletResponse response;

	private LoginController controller;

	@Before
	public void setUp() {
		request = new MockHttpServletRequest();
		response = new MockHttpServletResponse();
		controller = new LoginController();

		MockAuthenticator auth = new MockAuthenticator();
		auth.addUser(VALID_USERNAME, CORRECT_PASSWORD);
		controller.setAuthenticator(auth);
	}

	@Test
	public void wrongPasswordShouldRedirectToErrorPage() throws Exception {
		request.addParameter("j_username", "noSuchUsername");
		request.addParameter("j_password", "noSuchPassword");
		ModelAndView v = controller.handleRequest(request, response);

		assertEquals("wrongpassword", v.getViewName());
	}

	@Test
	public void validLoginForwardsToFrontPageAndStoresUsername() throws Exception {
		request.addParameter("j_username", VALID_USERNAME);
		request.addParameter("j_password", CORRECT_PASSWORD);
		ModelAndView v = controller.handleRequest(request, response);

		assertEquals("frontpage", v.getViewName());
	}
}

 

 

三.用JspTest 测试驱动JSP

 

JSPTEST是个开源库,他会把JSP编译成SERVLET类然后再执行此SERVLET。详细请登录其官网:

http://sourceforge.net/projects/jsptest/

 

jsptest里有一个叫做HtmlTestCase的抽象类,所有测试都需要继承这个类。HtmlTestCase提供了一些方法来模拟HTTP请求和渲染JSP文件以及做HTTP相关的验证等

JspTest默认在工程目录下开始寻找JSP文件。

 

测试FORM表单元素:

package com.tddinaction.j2ee.web.view.jsp.jsptest;

import net.sf.jsptest.HtmlTestCase;

public class LoginPageTest extends HtmlTestCase {

	@Override
	protected String getWebRoot() {
		return "src/test/resources/websrc/jsp";
	}

	public void testFormFieldsArePresent() throws Exception {
		get("/login.jsp");
		form().shouldHaveField("j_username");
		form().shouldHaveField("j_password");
		form().shouldHaveField("ddd");
		form().shouldHaveSubmitButton("login");

	}

	public void testPreviousUsernameIsRetained() throws Exception {
		setRequestAttribute("j_username", "bob");
		get("/login.jsp");
		form().field("j_username").shouldHaveValue("bob");
	}
}
//login.jsp

<%@ page language="Java" %>
<html>
  <body>
    <form>
    	<%
    	  String username = (String) request.getAttribute("j_username");
    	  if (username == null) username = "";
    	%>
      <input type="text" name="j_username" value="<%= username %>"/>
      <input type="password" name="j_password" />
      <input type="submit" name="ddd" value="login" />
    </form>
  </body>
</html>

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值