如何单元测试JSP呀。先说一下,我使用的IDE为m2eclipse~我从JUnit in Action的书中了解到可以使用cactus来实现,于是我就Google了很久及看maven官网,来使用maven3及插件cactus.integration.maven2来实现集成单元测试自动化(其中用到了war插件来打包及cargo插件来自动部署及开启关闭服务器)。但cactus.integration.maven2插件没有JUnit in Action书中提到的cactus目标,所有还是要手动输入URL来测试。但这几乎还是我不想要的。以上费了我两天中的业余时间,就为了单元测试JSP!命苦呀!
接着我又GOOGLE,说JUnit recipes有一章说了单元测试JSP。于是我就看了那一章的关于单元测试JSP的节~写下了代码:package jsps;import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;import java.util.*;import javax.servlet.ServletException;
import javax.servlet.http.*;
import junit.framework.*;import com.dongantech.eshop.model.*;
import com.dongantech.eshop.services.requests.*;
import com.dongantech.eshop.services.responses.*;
import com.dongantech.eshop.web.servlets.*;
import com.dongantech.eshop.services.handlers.*;import org.easymock.*;import com.meterware.servletunit.*;
import com.meterware.httpunit.*;public class TestMemberManagerServletResponseJsps extends DongAnShopJspFixture{
private ServletRunner servletRunner = null ;
private RequestHandler mockFindHandler = null;
private MockControl requestHandlerMockControl = null ;

public void setUp(){
try {
servletRunner = new ServletRunner(new File(DongAnShopJspFixture.getWebDeploymentDescriptorPath()),"/donganshop");

requestHandlerMockControl = MockControl.createControl(RequestHandler.class);
mockFindHandler = (RequestHandler) requestHandlerMockControl.getMock();
} catch (Exception e) {
e.printStackTrace();
fail("fail to new ServletRunner!");
}
}
public void testFoundResponseJsp() throws Exception{
Member preparedMember = new Member("lj");
Request preparedRequest = new SimpleRequest();
Map requestContext = new HashMap();
requestContext.put("memberFound",preparedMember);
preparedRequest.setContext(requestContext);
preparedRequest.setName(SimpleRequest.TYPE_FIND);

mockFindHandler.process(preparedRequest);
requestHandlerMockControl.setReturnValue(createMemberFoundResponse());
requestHandlerMockControl.replay();
////////////////////////////////////////////////////////////////////////////////////////////////////////
ServletUnitClient client = servletRunner.newClient();
WebRequest request = new GetMethodWebRequest("http://localhost/donganshop/members/memberManager");
request.setParameter("request",SimpleRequest.TYPE_FIND);
request.setParameter("username","lj");

InvocationContext invocationContext = client.newInvocation(request);
MemberManagerServlet servlet = (MemberManagerServlet) invocationContext.getServlet();
servlet.putIntoRequestHandlers("FIND",mockFindHandler);

HttpServletRequest httpReq = invocationContext.getRequest();
HttpServletResponse httpResp = invocationContext.getResponse();
servlet.getPages().put(SimpleResponse.TYPE_FOUND,MemberManagerServlet.PAGE_FOUND);
servlet.service(httpReq, httpResp);
WebResponse response = invocationContext.getServletResponse();

System.out.println(response.getText());
}
public void tearDown(){
requestHandlerMockControl.verify();
}
public Response createMemberFoundResponse(){
Response resp = new SimpleResponse();
List<Member> foundMembers = new ArrayList();
foundMembers.add(new Member("lj"));
foundMembers.add(new Member("lj520")); resp.setType(SimpleResponse.TYPE_FOUND);
resp.getContext().put("members", foundMembers); return resp;
}
}帖子过长,看下贴:

解决方案 »

  1.   

    Servlet代码如下:package com.dongantech.eshop.web.servlets;import javax.servlet.http.*;
    import javax.servlet.* ;import java.io.IOException;
    import java.util.*;
    import com.dongantech.eshop.model.*;
    import com.dongantech.eshop.services.requests.*;
    import com.dongantech.eshop.services.responses.*;
    import com.dongantech.eshop.persistences.factories.*;
    import com.dongantech.eshop.services.*;
    import com.dongantech.eshop.services.handlers.*;public class MemberManagerServlet extends HttpServlet{
    public static final String PAGE_FOUND = "/resources/members.jsp" ;
    public static final String PAGE_NOT_FOUND = "/resources/notFound.jsp" ;
    public static final String PAGE_EXCEPTION = "/resources/found.jsp" ;
    public static final String PAGE_ERROR = "/resources/error.jsp" ;

    private ManagerAbstractFactory managerFactory = null ;
    private Map requestHandlers = null ;
    private Map pages = null ;

    public MemberManagerServlet(){
    requestHandlers = new HashMap();
    pages = new HashMap();

    pages.put("FOUND",MemberManagerServlet.PAGE_FOUND);
    pages.put("NOT_FOUND",MemberManagerServlet.PAGE_NOT_FOUND);
    pages.put("EXCEPTION",MemberManagerServlet.PAGE_EXCEPTION);
    }
    public void init(ServletConfig config){
    try {
    super.init(config);
    String factoryImpl = config.getInitParameter("FACTORY_IMPL");
    ManagerAbstractFactory factory = ManagerFactoryUtil.createManagerFactory(factoryImpl);
    setManagerFactory(factory);

    } catch (ServletException e) {
    e.printStackTrace();
    }
    }
    public void doGet(HttpServletRequest httpReq,HttpServletResponse httpResp){
    Response response = processRequest(httpReq,httpResp);
    //TODO refactor
    response.getContext().put("httpServletRequest",httpReq);
    response.getContext().put("httpServletResponse",httpResp);
    /////////////////////////////////////////////////////////////
    try {
    deliver(response);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    public void doPost(HttpServletRequest httpReq,HttpServletResponse httpResp){
    Response response = processRequest(httpReq,httpResp);
    //TODO refactor
    response.getContext().put("httpServletRequest",httpReq);
    response.getContext().put("httpServletResponse",httpResp);
    /////////////////////////////////////////////////////////////
    try {
    deliver(response);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

    public Response processRequest(HttpServletRequest httpReq,HttpServletResponse httpResp){
    Response response = null ;
    String handlerName = httpReq.getParameter("request");
    RequestHandler handler = getHandler(handlerName);
    Request request = buildRequest(httpReq);
    try {
    response = handler.process(request);
    response.getContext().put("page",getPage(response.getType()));
    } catch (Exception e) {
    response = new SimpleResponse(SimpleResponse.TYPE_ERROR);
    e.printStackTrace();
    }
    return response ;
    }

    private Request buildRequest(HttpServletRequest httpReq) {
    Request request = new SimpleRequest(httpReq.getParameter("request"));
    Map requestContext = buildRequestContext(httpReq);
    request.setContext(requestContext);
    return request;
    }
    private RequestHandler getHandler(String handlerName) {
    if(requestHandlers.containsKey(handlerName)){
    return (RequestHandler) requestHandlers.get(handlerName);
    }
    throw new IllegalStateException("Request handler ["+handlerName+"] can not be found!");
    }
    public Map buildRequestContext(HttpServletRequest httpReq){
    Map context = new HashMap();

    String username = httpReq.getParameter("username");
    String memname = httpReq.getParameter("memname");
    String mobile = httpReq.getParameter("mobile");

    Member memberFound = new Member();
    memberFound.setUsername(username);
    memberFound.setMemname(memname);
    memberFound.setMobile(mobile);

    context.put("memberFound",memberFound);

    return context ;
    }
    public void deliver(Response response) throws ServletException, IOException{
    HttpServletRequest httpReq = (HttpServletRequest) response.getContext().get("httpServletRequest");
    HttpServletResponse httpResp = (HttpServletResponse) response.getContext().get("httpServletResponse");
    String page = (String) response.getContext().get("page");
    RequestDispatcher dispatcher = httpReq.getRequestDispatcher("resources/response.jsp");
    dispatcher.forward(httpReq, httpResp);
    }

    public void setManagerFactory(ManagerAbstractFactory theManagerFactory){
    managerFactory = theManagerFactory ;
    }

    public ManagerAbstractFactory getManagerFactory(){
    return managerFactory ;
    }

    public void putIntoRequestHandlers(String requestName,RequestHandler aHandler){
    requestHandlers.put(requestName,aHandler);
    }

    public String getPage(String thePageName){
    if(!(pages.containsKey(thePageName))){
    throw new IllegalStateException("There is not a page ["+thePageName+"] in response pages");
    }
    return (String) pages.get(thePageName);
    }

    public Map getPages(){
    return pages ;
    }
    }但我的测试代码都是抛出异常:org.apache.jasper.JasperException
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:373)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:295)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:245)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at com.meterware.servletunit.RequestDispatcherImpl.forward(RequestDispatcherImpl.java:54)
    at com.dongantech.eshop.web.servlets.MemberManagerServlet.deliver(MemberManagerServlet.java:118)
    at com.dongantech.eshop.web.servlets.MemberManagerServlet.doGet(MemberManagerServlet.java:51)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:740)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:853)
    at jsps.TestMemberManagerServletResponseJsps.testFoundResponseJsp(TestMemberManagerServletResponseJsps.java:64)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:585)
    at junit.framework.TestCase.runTest(TestCase.java:154)
    at junit.framework.TestCase.runBare(TestCase.java:127)
    at junit.framework.TestResult$1.protect(TestResult.java:106)
    at junit.framework.TestResult.runProtected(TestResult.java:124)
    at junit.framework.TestResult.run(TestResult.java:109)
    at junit.framework.TestCase.run(TestCase.java:118)
    at junit.framework.TestSuite.runTest(TestSuite.java:208)
    at junit.framework.TestSuite.run(TestSuite.java:203)
    at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)后来我又在JUnit Recipes书看到有这么一段,说写书的时候可独立使用的JSP引擎只有像Tomcat的内嵌的JSP引擎,使用起来的话,会要写许多代码~
    原文如下:
    DiscussionWe tried to find a standalone JSP engine that we could use to execute these tests
    and came up empty. We did try to use Jasper—the  JSP engine embedded in
    Apache Tomcat—but we had to write a considerable amount of code, mostly fak-
    ing context objects, just to get to the point where we could compile a JSP, let alone
    execute it. For that reason we abandoned this approach, preferring instead to use
    an actual container to process the  JSPs. Perhaps by the time you read this there
    will be a standalone JSP engine that you can use in its place. If so, you can compile
    and execute the JSP directly rather than going through a web container. So much
    the better.现在我真的为单元测试JSP犯愁了~
    我的项目分了四层(model/persistences/services/web)
    看了JUnit in Action使我能够测试每一层的代码逻辑并且测试速度很理想,唯独JSP测试起来就不行。现在我想要一个方法:
    1、不需要启动服务器,就能单元测试JSP
    2、可以自动化单元测试JSP
    3、并且自动可以与maven3集成
      

  2.   

    Hi,Somebody can help me~好心人,都去哪儿了?
      

  3.   

    JSP属于View层,我认为可以进行js test或ui test,除非你把很多业务都写在JSP了,否则不用像测试后台代码那样搞。
      

  4.   


    <%@ page language = "java" contentType = "text/xml; charset=utf8" %>
    <response type = "${requestScope.lastResponse.type}">
    <jsp:include page="${requestScope.lastResponse.page}"/>
    </response>
    <%@ page language = "java" contentType = "text/xml; charset=utf8" %>
    <%@ taglib prefix = "c" uri = "http://java.sun.com/jsp/jstl/core" %><c:forEach var = "curMember" items = "${requestScope.lastResponse.members}">
    <Member username = "${curMember.username}" memname = "${curMember.memname}">
    </Member>
    </c:forEach>其实是我固执而已,总觉得这事要做成,其实JSP里没有任何业务的,就显示逻辑~但我就想试着成功测试~还有,现在有没有出现可独立使用的简单易用的JSP引擎?
      

  5.   

    out.print 输出测试。看执行到那一块了!
      

  6.   

    兄弟,你没理解我的意思,这个测试肯定是会抛出异常~我是想找一个方法去单元测试JSP。
    单元测试做得好的话,个人观点:一般是不需要什么调试工具及out.print的。
      

  7.   

    哈哈。昨天我硬是把JUnit Recipes的Tenth Chapter与twelfth Chapter两章的关于此问题的内容打印出来,仔细看了一下,终于搞定了。今天圣诞节,祝大家节日快乐~
      

  8.   

    既然都是到jsp,这个就不是看数据了,而是看整个界面的展示效果。
    不要在代码单元测试了,在怎么单元你还是在代码里面,体现不出来,
    直接在浏览器回车
      

  9.   


    个人观点:就像JUnit in Action里面说过,那是测试你的眼睛洞察力及脑计算能力~这个可能每次的测试结果会也不同,由于你UI层输入数据的不同~JUnit Recipes里面有说过一个叫做“Golden Master”技术,可以第一次产生出来的结果作为基线(Baseline),未来代码(包括表示层的)有重构的的话测试都会知道的且通不过。至于是否直接看浏览器效果,我打算完全用Ajax技术,所以不看也罢~自已定义好显示框架,表示层(Ajax来处理客户端逻辑的话)可以完全交给别人做的~
    我测试的是逻辑,不是界面是否能够正常显示!
      

  10.   


    我可不是高手,就一个还没有项目经验的“准程序员”。不怕你笑话,我都没有公司实际工作经验的人。我是个大学毕业,工作一年后,在公司,做点小生意的人!有一年没有编过码了,因为我做生意去,最新两个月生意差,所以就重温旧业。记得毕业后就用PB就写过一个库存管理软件!你可以看看我的JSP代码,它有严重的错误。因为根本我就是JSP新手,不过我不怕,因为我打算用JSON技术作为服务器与客户端的数据交换格式!就像那个雅虎的Douglas Crockford说的,JSON真的很简单比起XML容易多了,而且更适合作用于数据交换。你还可以找找我代码里面需要重构的地方,我标了两处。还有几处。。