通过代码实例跟我学Struts2框架从入门到精通——对Action类进行单元测试和访问Servlet API
- 格式:pdf
- 大小:478.00 KB
- 文档页数:15
1.1通过代码实例跟我学Struts2框架从入门到精通——转换输出Struts2 框架中的Action基类中的成员属性的应用实例1.1.1Struts2框架中的JSon插件默认时并不转换输出Action基类中的成员属性由于Struts2框架的JSon插件,在默认状态时并不转换输出Action基类中的成员属性。
而在实际应用中可能会为多个不同的Action程序类提供一个共同的基类,并在该共同的基类中定义有共享的成员属性,从而避免在各个不同的Action程序类中重复地定义出该成员属性。
但如何转换输出在Action程序类的基类中所定义的成员属性为JSon对象字符串?作者在下文中将为读者详细地介绍具体的实现方法和相关的代码示例。
1、在示例项目中添加一个Action程序的基类BaseAction(1)该类的名称为BaseAction,包名称为com.px1987.querysystem.action,并继承于com.opensymphony.xwork2.ActionSupport基类(2)在Action程序的基类BaseAction中为各个不同的Action子类提供共享的成员属性。
2、将AJAXQueryStudentInfo类中的allStudentInfoPOList移到BaseAction基类中将AJAXQueryStudentInfo类中的allStudentInfoPOList移到Action程序的基类BaseAction类中的主要目的是为各个不同的Action子类提供共享的成员属性。
(1)allStudentInfoPOList集合变量代表查询返回的结果集合对象List<StudentInfoPO> allStudentInfoPOList=null;public List<StudentInfoPO> getAllStudentInfoPOList() {return allStudentInfoPOList;}public void setAllStudentInfoPOList(List<StudentInfoPO> allStudentInfoPOList) { this.allStudentInfoPOList = allStudentInfoPOList;}(2)修改后的基类BaseAction类的代码示例package com.px1987.querysystem.action;import java.util.List;import com.opensymphony.xwork2.ActionSupport;import com.px1987.dao.StudentInfoPO;public class BaseAction extends ActionSupport {private static final long serialVersionUID = 1L;/*** 下面的allStudentInfoPOList集合变量代表查询返回的结果集合对象*/List<StudentInfoPO> allStudentInfoPOList=null;public List<StudentInfoPO> getAllStudentInfoPOList() {return allStudentInfoPOList;}public void setAllStudentInfoPOList(List<StudentInfoPO> allStudentInfoPOList) { this.allStudentInfoPOList = allStudentInfoPOList;}public BaseAction() {}}3、将AJAXQueryStudentInfo类继承于BaseAction类而不再继承于ActionSupport类优化后的程序代码示例如下:package com.px1987.querysystem.action;import java.util.ArrayList;import com.opensymphony.xwork2.Action;import com.px1987.dao.StudentInfoPO;public class AJAXQueryStudentInfo extends BaseAction {/*** 类的序列化ID值*/private static final long serialVersionUID = 1L;/*** 下面的studentMajor变量代表表单传递的查询条件*/private String studentMajor=null;public String getStudentMajor() {return studentMajor;}public void setStudentMajor(String studentMajor) {this.studentMajor = studentMajor;}public AJAXQueryStudentInfo() {}/*** 下面的方法实现对基于AJAX的异步请求进行响应处理,由于在该方法中直接通过response对象将所获得的JSon对象格式字符串发送浏览器客户端,因此不需要返回结果String类型*/public String querySomeStudentInfos(){/*** 下面的代码模拟数据库的查询结果*/allStudentInfoPOList=new ArrayList<StudentInfoPO>();StudentInfoPO oneStudentPO=new StudentInfoPO();oneStudentPO.setStudentName("张三");oneStudentPO.setStudentAge(20);oneStudentPO.setStudentSex("男");oneStudentPO.setStudentMajor(studentMajor);allStudentInfoPOList.add(oneStudentPO);StudentInfoPO twoStudentPO=new StudentInfoPO();twoStudentPO.setStudentName("李四");twoStudentPO.setStudentAge(21);twoStudentPO.setStudentSex("女");twoStudentPO.setStudentMajor(studentMajor);allStudentInfoPOList.add(twoStudentPO);StudentInfoPO threeStudentPO=new StudentInfoPO();threeStudentPO.setStudentName("王五");threeStudentPO.setStudentAge(22);threeStudentPO.setStudentSex("男");threeStudentPO.setStudentMajor(studentMajor);allStudentInfoPOList.add(threeStudentPO);StudentInfoPO fourStudentPO=new StudentInfoPO();fourStudentPO.setStudentName("赵六");fourStudentPO.setStudentAge(19);fourStudentPO.setStudentSex("女");fourStudentPO.setStudentMajor(studentMajor);allStudentInfoPOList.add(fourStudentPO);return Action.SUCCESS;}}4、再部署和测试本项目的重构后的效果再次部署本Web应用程序项目,然后启动查询信息的表单页面,并在查询表单中输入“计算机应用”的专业名称字符串,如下图所示:点击表单中的“查询”按钮后,整个系统没有反映——在页面中无查询输出的结果数据。
1.1通过代码实例跟我学Struts2框架从入门到精通——Struts2框架系统的标签库及iterator标签的应用示例1.1.1标签技术概述1、为什么要提出标签库(1)分离页面和逻辑处理几乎是每个MVC框架的重要组成部分。
从Struts1开始,到Webwork2,SpringMVC,都有自己的定义的一套标签库。
但标签库,只是框架的一部分,为了解决页面显示数据、封装简单页面逻辑而产生的类HTML标记的组件。
(2)标签产生的初衷在JSP诞生之初,JSP提供了在HTML代码中嵌入Java代码的特性。
这种特性使得我们可以比较容易的利用Java这种强类型语言的优势,完成许多复杂的业务逻辑。
不过随着时间的推移,我们发现在HTML代码中嵌入过多的Java代码,非常不利于JSP 的维护和扩展。
对于动辄上千行的JSP代码,很多时候,程序员基本丧失了对JSP的维护能力。
基于上述的这个问题,我们尝试使用一种新的技术,来解决上面这些问题。
这也就是标签产生的初衷:1)尽量避免在JSP页面中使用Java代码,而改用类似HTML的标签的形式来表达页面逻辑,让逻辑与显示分离,提高JSP的可维护性;2)由于HTML自身的标签的表达能力不足,通过使用JSP Tag,可以对HTML语义进行扩展,从而完成许多HTML自身标签无法完成的工作2、应用标签技术的优缺点(1)主要的优点1)标签产生的初衷没有错,它的存在,能够简化JSP开发的难度,并对HTML的许多标签进行功能扩展;2)标签从效果上的确在一定程度上解决了在JSP页面中,避免使用Java代码的情况3)由于Java的语法与表现能力上的优势,使用Taglib能够极大程度的封装成块的HTML代码,从而形成一套完整的页面组件,能够极大的简化页面开发(2)主要的缺点●标签只是为了尝试避免在JSP页面中使用Java代码,实际上,这种情况很难避免。
有时候,为了达到这个目的,反而带来了更多的代码和沉重的维护成本。
1.1通过代码实例跟我学Struts2框架从入门到精通——如何自定义Struts2框架中的拦截器组件的应用实例1.1.1回顾和进一步了解Action组件的生命周期1、Struts2中的拦截器层层把Action进行包裹2、整个结构就如同一个堆栈,除了Action以外,堆栈中的其他元素是Interceptor(1)Action位于堆栈的底部由于堆栈“先进后出”的特性,如果试图把Action拿出来执行,必须首先把位于Action 上端的Interceptor拿出来执行。
这样,整个执行就形成了一个递归调用。
(2)每个位于堆栈中的Interceptor,除了需要完成它自身的逻辑,还需要完成一个特殊的执行职责。
这个执行职责有3种选择:1)中止整个执行,直接返回一个字符串作为resultCode2)通过递归调用负责调用堆栈中下一个Interceptor的执行3)如果在堆栈内已经不存在任何的Interceptor,调用Action3、Struts2的拦截器结构的设计,实际上是一个典型的责任链模式的应用首先将整个执行划分成若干相同类型的元素,每个元素具备不同的逻辑责任,并将他们纳入到一个链式的数据结构中(我们可以把堆栈结构也看作是一个递归的链式结构),而每个元素又有责任负责链式结构中下一个元素的执行调用。
这样的设计,从代码重构的角度来看,实际上是将一个复杂的系统,分而治之,从而使得每个部分的逻辑能够高度重用并具备高度可扩展性。
所以,Interceptor结构实在是Struts2/Xwork设计中的精华之笔。
1.1.2应用Struts2中的拦截器技术---自定义拦截器组件1、添加一个拦截器组件类名称为AuthorizedUserInterceptor、包名称为com.px1987.sshwebcrm.interceptor、并且从com.opensymphony.xwork2.interceptor.AbstractInterceptor基类进行继承。
1.1通过代码实例跟我学Struts2框架从入门到精通——Struts2框架入门示例1.1.1Struts2 框架的入门示例1、新建立一个Web项目(1)项目名称为sshwebcrm、并且添加JSTL标签库但最好将项目的J2EE系统库的版本选择为J2EE5.0版,以便能够应用MyEclipse的可视化帮助。
(2)设置编译环境为JDK1.6Struts2默认需要Java5的运行环境,和支持Servlet API 2.4,JSP API 2.0的Web容器。
2、在项目中添加图片等资源文件(1)各个资源文件所在的目录当然,如果没有这些资源文件也是可以的,只是更符合实际的应用项目。
(2)最终的结果目录及文件3、在项目中添加index.jsp页面<%@ page isELIgnored="false" pageEncoding="GB18030"%><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="/1999/xhtml"><head><title>蓝梦集团CRM系统首页</title><meta http-equiv="pragma" content="no-cache" /><meta http-equiv="cache-control" content="no-cache" /><meta http-equiv="expires" content="0" /><meta http-equiv="keywords" content="蓝梦集团,CRM,账户" /><meta http-equiv="description" content="这是蓝梦集团CRM系统" /></head><body><jsp:include page="/commonPage/pageHead.jsp" ></jsp:include><jsp:include page="/commonPage/navMenuBar.jsp" ></jsp:include><br/><div id="someOnePageContent" ><strong>这是蓝梦集团CRM系统(客户关系系统)的首页内容</strong></div><br/><jsp:include page="/commonPage/authorInfo.jsp" ></jsp:include></body></html>在该页面中应用<jsp:include >动作标签包含其它的公共资源文件,从而形成一个完整结构的页面。
1.1通过代码实例跟我学Struts2框架从入门到精通——Struts2框架的Action向JSP页面返回JSon对象字符串的应用实例(第3部分)1.1.1应用JQuery的迭代函数优化程序代码1、应用JavaScript中的for-each类型的循环优化程序代码由于从服务器端程序返回的结果为集合对象,为了简化对集合的迭代循环实现的代码,可以应用JavaScript中的for-each类型的循环优化程序代码。
如下为完善后的代码示例:$().ready(function(){/*** 为查询按钮动态关联鼠标单击的click事件*/$('#queryInfoInputTagID').click(function() {/*** 在click事件响应代码中,首先获得操作者所输入的相关查询参数值,然后再应用ajax函数向Web服务器端相关程序发送异步Http请求。
该Http请求为Post请求。
*/var inputStudentMajor = $("#inputMajorTagID").val();$.ajax({type: "post",url: queryRequestURL,dataType: "json",data:{studentMajor:inputStudentMajor},success : showQueryStudentInfoInSomeTable ,error:showAJAXErrorInfo});});/**下面的showAJAXErrorInfo函数是显示在请求处理的过程中的各种错误信息*/function showAJAXErrorInfo(XMLHttpRequest, errorInfoText, errorObject){ window.alert("调用中出现如下的错误:"+errorInfoText.toString());}/**下面的showQueryStudentInfoInSomeTable函数是根据服务器端程序的返回JSon处理的结果值,并对结果数据进行解析以获得相关的数据项目,然后在页面中显示输出相关的数据项目*/function showQueryStudentInfoInSomeTable(jsonAllStudentObjectFromServlet){ /**oneTRTagObject 代表<tr>标签对象*/var oneTRTagObject;/**首先获得表格<table>标签对象*/var showDataTableTagObject=window.document.getElementById(showDataTableTagID_Global);var showDataTableTagTBodyObject =window.document.getElementById(showDataTableTagTBodyID_Global);/**删除<tbody>标签中的原来的所有的<tr>标签,从而达到删除原来的查询结果数据*/while(showDataTableTagTBodyObject.rows.length >0){showDataTableTagTBodyObject.deleteRow(showDataTableTagTBodyObject.rows.length-1) ;}/**再添加新的表格数据行,其中的oneStudentInfoObjectKey代表从对象数组中获得某个学生信息PO对象的键(Key)名称,而不是PO对象本身。
1.1通过代码实例跟我学Struts2框架从入门到精通——Struts 2框架中的转换器相关应用技术及示例1.1.1Struts 2框架中的转换器相关应用技术1、在Web服务器端所获得的数据为String开发Web应用程序与开发传统桌面应用程序不同,Web应用程序实际上是分布个不同的主机(当然也可以同一个主机,不过比较少见)上的两个进程之间互交。
这种互交建立在HTTP之上,它们互相传递是都是字符串。
换句话说,服务器可以的接收到的来自用户的数据只能是字符串或字符数组,而在服务器上的对象中,这些数据往往有多种不同的类型,如日期(Date),整数(int),浮点数(float)或自定义类型(UDT)等,如图1所示。
因此,我们需要服务器端将字符串转换为适合的类型。
同样的问题也发生在使用UI展示服务器数据的情况。
HTML的Form控件不同于桌面应用程序可以表示对象,其值只能为字符串类型,所以我们需要通过某种方式将特定对象转换成字符串。
2、常规的实现方式(1)在服务器端将String---DateDate birthday = DateFormat.getInstance(DateFormat.SHORT).parse(strDate);(2)在表示层<input type="text" value="<%= DateFormat.getInstance(DateFormat.SHORT).format(birthday) %>" />3、利用Struts2框架中的Converter(1)在HTML中,并没有数据类型的概念,任何数据都被当作字符串或者字符串数组来传递(2)Struts2框架为开发者提供了一些内建的类型转换比如基本类型之间的转换、“1984-08-27”格式的字符串能够被正确的转换为Date类型等等或者对于将String转换为int等简单类型,Struts2已经提供。
1.1通过代码实例跟我学Struts2框架从入门到精通——如何应用Struts 2框架中的Action链(Action Chaining)的默认拦截器应用实例1、应用的背景在Struts2中,一次用户的请求可能是由多个不同的Action共同完成。
每个Action可以只实现自己本身的功能单元,这样我们可以根据业务需要为用户的一次请求选择一个或多个Action功能单元来实现。
2、应用的要求在这样的多个Action之间可以通过chain拦截器共享数据。
如果请求由ActionOne 链到ActionTwo,如果这时ActionTwo需要获得ActionOne所处理的数据,就需要为ActionTwo 添加chain拦截器。
3、实现的示例(实现将“doUpdateUser”和“doDeleteUser”相互组合)(1)在本项目的loginSuccess.jsp文件中再增加一个显示输出<%@ page contentType="text/html; charset=GB2312" %><%@ taglib prefix = "s" uri="/struts-tags" %><html > <head > <title > 登陆成功</title > </head ><body ><h2><s:property value ="resultMessageOne" /></h2 > <br><h2><s:property value ="resultMessage" /></h2 ></body ></html >这样可以使得在最终的结果显示的loginSuccess.jsp页面文件中可以分别获得不同的Action程序类中所产生的处理结果数据。
struts2学习笔记(五)在Action类中进行数据的输入校验不使用struts标签的话,在FORM元素中的ACTION属性的值后面必须手动添加" .action "用HTML标签来编写表单,在数据出错返回原来页面时想要显示框架自动添加的错误信息要用Struts标签:<s:fielderror></s:fielderror>要再次显示表单中一部分正确的信息,在HTML标签中可以value=”${requestScope.组件名}”使用struts标签会自动显示返回的错误信息,并保留显示部分正确信息.使用STRUTS标签来显示addFieldError中的错误信息于页面比较两个日期(DATE)先后:Calendar c1=Calendar.getInstance();c1.setTime(date1);//date1为一个Date对象Calendar c2=Calendar.getInstance();c2.setTime(date2);c1.before(c2);//比较两个日期的先后,返回一个boolean值value="${ername}"不能自动转化为INT类型的值被转化为0,并生成一条错误信息放入addFieldErrorstruts.xml中的constant元素用来存放常量先进行类型转换再进行输入校验Struts.xml文件中<package>元素前这样写:<constant name="struts.custom.i18n.resources" value="message"></constant>classes目录下的message.properties文件(文件名如上一行中绑定的value值一致),内容如下:全局xwork.default.invalid.fieldvalue={0} error任何属性在转换过程中出错,就会调用message.properties中的指定,{0}为用出错的属性名,并在后面加上ERROR 0是用来匹配哪个出错属性(如用页面中该组件的name值来代替)可以在action类下面:XAction.properties文件(文件名与ACTION类相同);写法:局部invalid.fieldvalue.age=age conversion errorage为在action类的转化过程中可能出错的属性名,=后面的字符串用来替换在出错后由框架自动添加进去的错误信息.要用中文来代替输入错误信息的话,需要对中文先进行编码,可以用到JDK/BIN目录下的native2ascii.exe程序,使用方法在DOS窗口中输入命令native2ascii回车后在新的一行输入你要转换的中文,回车后就行,将转换后的结果复制到properties文件中就可以在页面中显示中文提示信息了.也可以进行文件2文件的转换,命令如下:native2ascii test.txt result.properties 需要在要转换的文件目录下执行该命令全局要在struts.xml文件中用<constant>元素定义,并在classes目录下编写相应的properties文件,局部只需在相应的包内编写相应文件名的属性文件类型转换和输入校验的流程:1 先对STRUTS客户端传来的数据进行类型转换2 类型转换完成后再进行输入校验'3 如果类型转换和输入校验都没有错误发生,那么进入EXECUTE方法,(调用商业逻辑)注意:如果类型转换不成功也要进行输入校验(如INT类型转换出错自动赋值为O,STRING类型转换出错自动为NULL)。
1.1通过代码实例跟我学Struts2框架从入门到精通——对Action类进行单元测试和访问Servlet API1.1.1回顾有关单元测试的一些概念1、什么是单元测试“容器外”(在服务器程序——在Tomcat之外)对某个Java类中的某个功能方法(也就是单元测试中的工作单元)所实现的测试。
实施单元测试的目的是“验证”该功能方法是否正常(是否满足要求)。
2、什么是单元测试中的“单元”能够“独立”完成某个功能的方法。
经常与单元测试联系起来的另外一些开发活动包括代码走读(Code review),静态分析(Static analysis)和动态分析(Dynamic analysis)。
静态分析就是对软件的源代码进行研读,查找错误或收集一些度量数据,并不需要对代码进行编译和执行。
动态分析就是通过观察软件运行时的动作,来提供执行跟踪,时间分析,以及测试覆盖度方面的信息。
3、为什么要进行单元测试我们编写代码时,一定会反复检查和调试保证它能够编译通过。
如果没有通过编译,该代码是无法执行。
但尽管代码通过了编译,也只能说明它没有语法错误;但无法保证它的语义或者逻辑、功能也一定正确。
如何验证或者发现代码中这些方面的错误?单元测试可以轻易地发现代码中这些方面的错误。
4、由谁具体实施单元测试的工作由于单元测试本身是编码工作的一部分,当然应该由该程序的开发人员(程序员)完成;也就是说,经过了单元测试的代码才是已完成的代码,提交产品代码时也要同时提交测试代码和单元测试的结果。
5、如何进行单元测试(1)采用什么框架——JUnit()MyEclipse中有它的系统库(2)如何编程测试程序(类)——测试用例(Test Case),包含有一系列的测试方法测试用例(Test Case)是为某个特殊目标而编制的一组测试程序——该程序包括测试中所需要的输入参数、执行条件以及预期结果,并通过该测试用例验证某个程序或核实是否满足某个特定需求。
(3)如何编程测试用例——采用MyEclipse中的可视化向导6、区分单元测试和集成测试(1)单元测试它是在开发过程中的对类中的方法测试——小规模的测试,功能测试,并且由开发人员完成;(2)集成测试它是在系统在装配过程中的测试,接口和配合测试,并且由测试小组中的测试人员7、集成测试(1)集成测试也叫组装测试或联合测试。
在单元测试的基础上,将所有模块按照设计要求(如根据结构图〕组装成为子系统或系统,进行集成测试。
(2)为什么还要进行集成测试由于单元测试具有不彻底性,实践表明,一些模块虽然能够单独地工作(通过单元测试),但并不能保证连接起来也能正常的工作。
程序在某些局部反映不出来的问题,在全局上很可能暴露出来。
另外的原因是,模块相互调用时接口会引入许多新问题。
例如,数据经过接口可能丢失;一个模块对另一模块可能造成不应有的影响;几个子功能组合起来不能实现主功能;误差不断积累达到不可接受的程度;全局数据结构出现错误,等等。
(3)集成测试中的主要考虑的问题1)在把各个模块连接起来的时候,穿越模块接口的数据是否会丢失;2)各个子功能组合起来,能否达到预期要求的父功能;3)一个模块的功能是否会对另一个模块的功能产生不利的影响;4)全局数据结构是否有问题;5)单个模块的误差积累起来,是否会放大,从而达到不可接受的程度。
1.1.2对Action类进行单元测试单元测试困难是Struts一大缺点。
现在让我们在体验一下,在Struts 2.0中是如何进行测试的。
1、添加一个测试项目——遵守测试项目和被测试项目(应用系统项目)相互分离由于测试用例的代码是在开发过程中产生的,不属于最终的产品的一部分。
(1)新增加一个Java项目(2)测试项目的名称为TestSSHWebCRM2、在测试项目中引用被测试项目和添加JUnit系统包(本项目采用JUnit4)(1)在测试项目中引用被测试项目——能够在测试项目中访问被测试项目中的代码(2)在测试项目中添加JUnit系统包(本项目采用JUnit4,)(3)下载Junit4.8.1版本的系统库文件(4)在测试项目中添加Junit的系统库文件(5)也可以直接采用Eclipse中的JUnit4.X的系统库(6)将出现下面的结果3、在测试项目中添加与Struts2有关的系统包文件4、在测试项目中添加JUnit的TestCase(测试用例——也就是测试的功能类)(1)新增加测试用例类(2)下载Junit Test Case菜单项目(3)输入包名称为com.px1987.sshwebcrm.testaction,类名称为Test UserInfoManageActionModel,被测试的类选择为erInfoManageActionModel(4)选择所需要测试的方法(5)将自动地创建出下面的模板形式的测试用例类5、编程该测试用例(1)理解测试用例类中的各个标准方法的执行过程(2)编程测试用例——针对UserInfoManageActionModel类的测试用例package com.px1987.sshwebcrm.testaction;import static org.junit.Assert.*;import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;import com.opensymphony.xwork2.Action;import erInfoManageActionModel; import erInfoActionForm;public class TestUserInfoManageActionModel {private static UserInfoManageActionModel userInfoManageAction =null;@BeforeClasspublic static void setUpBeforeClass() throws Exception {userInfoManageAction=new UserInfoManageActionModel();}@AfterClasspublic static void tearDownAfterClass() throws Exception {userInfoManageAction=null;}@Beforepublic void setUp() throws Exception {}@Afterpublic void tearDown() throws Exception {}@Testpublic void testDoUserLogin() {UserInfoActionForm oneUserInfo=new UserInfoActionForm(); //(1)构建测试参数oneUserInfo.setVerifyCodeDigit("UFO123");oneUserInfo.setUserName("yang1234");oneUserInfo.setUserPassWord("12345678");oneUserInfo.setType_User_Admin(1);userInfoManageAction.setOneUserInfo(oneUserInfo); //模拟Struts2的拦截器参数注入String resultMessage = userInfoManageAction.doUserLogin(); //(2)对被测试方法进行调用// Assert.assertTrue(resultMessage.equals(ActionSupport.SUCCESS));assertTrue(resultMessage.equals(Action.SUCCESS));//(3)断言(判断返回的值是否为期望的值)}(3)编程测试用例——针对UserInfoAction 类的测试用例——作为课后作业package com.px1987.sshwebcrm.testaction;import junit.framework.Assert;import org.junit.After;import org.junit.AfterClass;import org.junit.Before;import org.junit.BeforeClass;import org.junit.Test;import com.opensymphony.xwork2.ActionSupport;import com.px1987.sshwebcrm.action. UserInfoAction;public class TestUserInfoAction {static UserInfoAction oneUserInfoAction =null;@BeforeClasspublic static void setUpBeforeClass() throws Exception {oneUserInfoAction=new UserInfoAction();}@AfterClasspublic static void tearDownAfterClass() throws Exception {oneUserInfoAction=null;}@Beforepublic void setUp() throws Exception {@Afterpublic void tearDown() throws Exception {}@Testpublic void testDoUserLogin() {//(1)给出测试过程中所需要的参数oneUserInfoAction.setUserName("yang");oneUserInfoAction.setUserPassWord("1234");oneUserInfoAction.setVerifyCodeDigit("123456");oneUserInfoAction.setType_User_Admin(1);//(2)对被测试方法进行调用String returnResult=oneUserInfoAction.doUserLogin();//(3)检查返回值是否为所期望的值(利用断言语句)Assert.assertTrue(returnResult.equals(ActionSupport.SUCCESS)); //断言}@Testpublic void testDoUserRegister() {oneUserInfoAction.setUserName("yang");oneUserInfoAction.setUserPassWord("1234");oneUserInfoAction.setVerifyCodeDigit("123456");oneUserInfoAction.setType_User_Admin(1);String returnResult=oneUserInfoAction.doUserRegister();Assert.assertTrue(returnResult.equals(ActionSupport.SUCCESS)); //断言}@Testpublic void testDoUpdateUser() {}@Testpublic void testDoDeleteUser() {}注意:如果在Action类中涉及request/response/session则不能采用该方式。