给servlet写单元测试的总结

    技术2022-05-11  74

    servlet的测试一般来说需要容器的支持,不是像通常的java类的junit测试一样简单,   下面通过对HelloWorld代码的测试阐述了几种servlet测试方法。   被测试的HelloWorld类的代码如下:   /**  * 被测试的servlet  */ import java.io.IOException;   import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.cactus.WebRequest; import org.apache.cactus.server.HttpServletRequestWrapper;   public class HelloWorld extends HttpServlet{    public void saveToSession(HttpServletRequest request) {          request.getSession().setAttribute("testAttribute",request.getParameter("testparam"));  }    public void doGet(HttpServletRequest request,HttpServletResponse response) throws IOException{          String username=request.getParameter("username");          response.getWriter().write(username+":Hello World!");          }    public boolean authenticate(){                   return true;    } }   以HelloWorld为例,我总结了Servlet的多种测试方法如下:   一.使用HttpUnit测试   import com.meterware.httpunit.GetMethodWebRequest; import com.meterware.httpunit.WebRequest; import com.meterware.httpunit.WebResponse; import com.meterware.servletunit.InvocationContext; import com.meterware.servletunit.ServletRunner; import com.meterware.servletunit.ServletUnitClient; import junit.framework.Assert; import junit.framework.TestCase;   public class HttpUnitTestHelloWorld extends TestCase {    protected void setUp() throws Exception {   super.setUp();  }    protected void tearDown() throws Exception {   super.tearDown();  }    public void testHelloWorld() {      try {    // 创建Servlet的运行环境    ServletRunner sr = new ServletRunner();    // 向环境中注册Servlet    sr.registerServlet("HelloWorld", HelloWorld.class.getName());      // 创建访问Servlet的客户端    ServletUnitClient sc = sr.newClient();    // 发送请求    WebRequest request = new GetMethodWebRequest(" http://localhost/HelloWorld");    request.setParameter("username", "testuser");    InvocationContext ic = sc.newInvocation(request);    HelloWorld is = (HelloWorld) ic.getServlet();      // 测试servlet的某个方法    Assert.assertTrue(is.authenticate());    // 获得模拟服务器的信息    WebResponse response = sc.getResponse(request);    // 断言    Assert.assertTrue(response.getText().equals("testuser:Hello World!"));   } catch (Exception e) {    e.printStackTrace();   }  }   }   上述例子其实是junit的一个测试例子,在其中使用了httpunit模拟的servlet环境,使用上述方法测试   servlet可以脱离容器,容易把该测试写入ant或maven脚本,让测试进行。   httpunit网址: http://httpunit.sourceforge.net/   使用该种方法测试的弱点就是:如果要使用request(response)的 setCharercterEncoding方法时,测试会出现一些问题,   而且httpunit在测试servlet行为时,采用的是完全模拟浏览器,有时测试比较难写。   二 使用cactus测试   /**  * cactus测试servlet的例子  * 必须要有tomcat的支持  *   */   import junit.framework.Test; import junit.framework.TestSuite; import org.apache.cactus.ServletTestCase; import org.apache.cactus.WebRequest; import org.apache.cactus.WebResponse; public class CactusHelloWorld extends ServletTestCase{         HelloWorld servlet;      public CactusHelloWorld(String theName) {          super(theName);      }        protected void setUp() throws Exception {          super.setUp();          servlet = new HelloWorld();      }        protected void tearDown() throws Exception {          super.tearDown();      }        /**       * 测试方法测试参数在此设置       *       * @param webrequest       */        public void beginSaveToSessionOK(WebRequest request) {          request.addParameter("testparam", "it works!");      }           /**       * 测试方法测试参数在此设置       *       * @param webrequest       */        public void beginDoGet(WebRequest request) {          request.addParameter("username", "testuser");      }        /**       * 调用servlet的测试方法       *        */      public void testSaveToSessionOK() {          servlet.saveToSession(request);          assertEquals("it works!", session.getAttribute("testAttribute"));      }        public void testDoGet() {          try {              servlet.doGet(request, response);          } catch (Exception e) {              e.printStackTrace();          }      }        /**       * 此方法可以判断测试方法的输出,会传递测试方法的reponse给end***,并且格式化为cactus       * 的WebResponse或者可以跟httpunit集成,格式化为httpunit的response       *       * @param response       */      public void endDoGet(WebResponse response) {          String content;                  content = response.getText();          assertEquals("testuser:Hello World!", content);      } }   cactus具备丰富灵活的测试功能,如要测试doGet方法,分为beginDoGet(模拟测试参数设置)、DoGet(执行测试)、endDoGet(状态结果验证)   相比httpunit来说,写测试更为容易,测试servlet更为专业,流程更为清晰,但是cactus需要容器支持,使得测试不可以自动进行,但是   如果使用一个嵌入式的容器,测试就可以自动了。   cactus是一个servlet和jsp的测试框架: http://jakarta.apache.org/cactus/getting_started.html   三 使用Jetty作为嵌入式容器测试servlet.   /**  * 一个关于嵌入式jetty测试的例子,jetty作为stubs的一个例子  *   */ package com.easyjf.testexample;   import org.mortbay.jetty.Connector; import org.mortbay.jetty.Server; import org.mortbay.jetty.bio.SocketConnector; import org.mortbay.jetty.servlet.ServletHandler;   import com.meterware.httpunit.WebClient; import com.meterware.httpunit.WebConversation; import com.meterware.httpunit.WebResponse;   import junit.framework.Assert; import junit.framework.TestCase;   public class JettySampleTest extends TestCase {    Server server;  protected void setUp() throws Exception {       //通过代码设置并启动一个服务器,该服务器是servlet的测试容器       super.setUp();       server = new Server();       Connector connector=new SocketConnector();       connector.setPort(80);       server.setConnectors(new Connector[]{connector});       ServletHandler handler=new ServletHandler();       server.setHandler(handler);       handler.addServletWithMapping("HelloWorld", "/");       server.start();  }    protected void tearDown() throws Exception {   super.tearDown();   server.stop();  }    public void testHellWorld() {   try {    WebConversation wc = new WebConversation();    WebResponse web = wc.getResponse(" http://127.0.0.1/HelloWorld");    String result=web.getText();    Assert.assertEquals(result,"it works!");   } catch (Exception e) {    e.printStackTrace();   }  } }   可以发现,jetty可以充当一个servlet的容器,方便的是,jetty支持嵌入式服务,即可以通过代码来启动,   所以要写自动测试的例子很方便,可以结合httpunit或者cactus进行servlet测试。   jetty主页: http://docs.codehaus.org/display/JETTY/Embedding+Jetty 四 使用mock对象,此处使用easymock   import java.io.PrintWriter; import java.io.Writer; import javax.servlet.ServletConfig; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;   import junit.framework.Assert; import junit.framework.TestCase; import static org.easymock.EasyMock.*; public class MockTestServlet extends TestCase {       public void testService() throws Exception {         System.out.println("service");         HttpServletRequest request = createMock(HttpServletRequest.class);         HttpServletResponse response = createMock(HttpServletResponse.class);         //Creating the ServletConfig mock here         ServletConfig servletConfig = createMock(ServletConfig.class);         //Creating the ServletContext mock here         ServletContext servletContext = createMock(ServletContext.class);                  //Create the target object                  HelloWorld4 instance = new HelloWorld();         //初始化servlet,一般由容器承担,一般调用servletConfig作为参数初始化,此处模拟容器行为         instance.init(servletConfig);           //在某些方法被调用时设置期望的返回值,如下这样就不会去实际调用servletConfig的getServletContext方法,而是直接返回           //servletContext,由于servletConfig是mock出来的,所以可以完全控制。         expect(servletConfig.getServletContext()).andReturn(servletContext).anyTimes();         expect(request.getParameter("username")).andReturn("testuser");         PrintWriter pw=new PrintWriter(System.out,true);         expect(response.getWriter()).andReturn(pw).anyTimes();                  //以上均是录制,下面为重放,该种机制为easymock测试机制,要理解请看easymock测试的一些资料         replay(request);         replay(response);         replay(servletConfig);         replay(servletContext);           instance.doGet(request, response);         pw.flush();                   //验证结果是否预期,如果预期,则会在pw上写出testuser.         verify(request);         verify(response);         verify(servletConfig);         verify(servletContext);    } }   mock测试注重行为,mock对象其实都是模拟的对象,方法一般直接给出一个返回值,没有具体的对象逻辑,mock对象   是用来帮助测试要测试的类的。比如要测试servlet的内部行为,又不想要容器等环境,就可以采用mock测试。   easymock是mock测试的一个框架: http://www.easymock.org/  

    最新回复(0)