`
yangjizhong24
  • 浏览: 399620 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

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>

 

 

 

 

分享到:
评论
1 楼 jellyx 2012-07-11  
JSPTEST 一开始是报没各种JAR包,然后从tomcate复制进来,最后又报很多错。总之恶性循环的。怎么办呢

相关推荐

    Python Web开发:测试驱动方法1

    《Python Web开发:测试驱动方法》是一本面向Web开发者的实践指南,作者Harry J.W. Percival通过这本书引导读者掌握使用Python进行测试驱动开发(Test-Driven Development, TDD)的方法。书中内容涵盖了从基础到高级...

    node-tdd:使用Node和TDD启动测试应用程序

    **标题解析:** "node-tdd:使用Node和TDD启动测试驱动开发应用程序" 这个标题表明我们将探讨如何利用Node.js环境以及测试驱动开发(Test-Driven Development, TDD)的方法来创建一个应用程序。Node.js是基于Chrome ...

    angular-tdd:用角度进行测试驱动的开发

    在这个“angular-tdd:用角度进行测试驱动的开发”的主题中,我们将深入探讨如何在Angular项目中实施TDD,以及如何利用JavaScript进行有效的测试。 首先,让我们了解什么是Angular。Angular是由Google维护的一个开源...

    测试驱动开发的艺术Test.Driven.TDD.and.Acceptance.TDD.for.Java.Developers

    对于Java开发者来说,TDD的应用还需要掌握相关工具和库,如Junit、Mockito用于单元测试,Selenium或Appium进行Web或移动应用的端到端测试,以及FitNesse或Cucumber进行验收测试。书中可能还会涵盖如何在IDE(如...

    关于测试和TDD

    标题中的“关于测试和TDD”指的是Test-Driven Development(测试驱动开发)这一软件开发实践。测试驱动开发是一种敏捷开发方法论,强调在编写实际功能代码之前先编写测试用例。这种方式有助于确保软件质量,降低错误...

    测试驱动器:用于编写Web组件测试的有思想的库

    Test Drive是一个自以为是,但与框架无关的工具,匹配器和帮助器的集合,用于高效地进行Web应用程序,GUI和客户端组件的“测试驱动开发”。 基于现有的开源项目以及原始的贡献和想法,它不仅提供实用且有效的解决...

    django-tdd-docker:测试驱动的Docker + Django项目(TestDriven.io教程)

    【标题】"测试驱动的Docker + Django项目"是基于TestDriven.io提供的教程,旨在指导开发者如何使用TDD(测试驱动开发)方法构建一个结合Docker的Django Web应用程序。这个教程涵盖了Python语言、Django框架以及...

    test.driven.tdd.and.acceptance.tdd.for.java.developers

    - **Web组件的测试驱动开发**:讨论如何为Java Web应用中的组件编写单元测试和集成测试。 - **数据访问的测试驱动开发**:探讨如何使用TDD来开发数据访问层,包括数据库交互的测试。 - **处理不可预测行为的测试驱动...

    bootcamp-tdd:在 BootCamp 期间用于向考生展示如何使用 git,并让他们开始进行测试驱动开发

    "bootcamp-tdd" 是一个训练项目,旨在向参与 BootCamp 的学员介绍如何使用版本控制系统 Git,并引导他们入门测试驱动开发(TDD)的方法。TDD 是一种软件开发实践,强调先编写测试用例,再编写满足这些测试的代码,...

    企业级项目的Web自动化测试工程化实践.pdf

    1.3 开发模式:TDD(测试驱动开发)和BDD(行为驱动开发) - TDD:先编写测试用例,再编写实现代码,确保代码满足需求。 - BDD:关注用户行为,通过定义可执行的规格来驱动开发。 【单元测试(Unit Testing)】 ...

    精通ASP.NET Web程序测试.rar

    TDD(测试驱动开发)和BDD(行为驱动开发)等实践提倡在开发过程中编写测试,确保改动不会引入新的错误。 在压缩包“极品时刻表”中,可能包含了一个示例的ASP.NET Web应用程序或测试用例,用于演示上述测试方法的...

    java高手真经_系统架构卷:java.web系统设计与架构

    此外,书中还会介绍如何进行测试驱动开发(TDD),使用JUnit和Mockito等工具进行单元测试,以及如何进行集成测试和性能测试,确保代码的质量和系统的稳定性。 最后,对于Java Web系统的持续集成和持续部署(CI/CD)...

    testdrivenio:测试驱动

    测试驱动开发(Test-Driven Development, TDD)是一种软件开发实践,它强调在编写实际代码之前先编写测试。这种做法可以提高代码质量、减少错误并促进更好的设计。"testdrivenio" 指的可能是一个关于 TDD 的教程或...

    C#测试驱动开发.rar

    一、测试驱动开发(TDD)概述 1.1 TDD的核心原则:红-绿-重构 TDD遵循"红-绿-重构"的循环模式。首先,编写一个失败的测试用例(红色),然后编写刚好使该测试通过的最小量的代码(绿色),最后对新代码进行重构,以...

    AE 组件式开发及应用

    3. 测试驱动开发(TDD):编写单元测试确保组件的正确性。 4. 版本控制:使用Git等工具管理代码版本,便于协同开发和回溯。 5. 文档记录:清晰的组件文档有助于理解和使用。 六、AE组件式开发的挑战 虽然组件化开发...

    net软件测试实战技术基础知识大全

    测试驱动开发 (TDD) - **Visual Studio 支持**:提供了 TDD 的支持。 - **Web 测试**:支持 Web 应用的测试。 ### 13. 单元测试工具 - **NTime/AQTime**:性能测试工具。 - **VS 提供的工具**:包括性能分析和...

    软件测试资料--自动测试

    9. 测试驱动开发(TDD)与行为驱动开发(BDD): TDD强调先编写测试再实现代码,BDD则关注从用户行为角度定义测试,两者都鼓励自动化测试的早期引入。 10. 自动化测试挑战: - 初始投资:自动化测试工具和框架的学习...

    软件测试经典面试题 (超实用)

    - **网络兼容性**:测试软件在网络条件变化下的表现。 #### 2. 判断程序慢的原因 - **区分问题来源**: - **程序层面**:分析代码逻辑,查找性能瓶颈。 - **硬件层面**:检查CPU、内存、硬盘等资源是否充足。 -...

Global site tag (gtag.js) - Google Analytics