給servlet寫(xiě)單元測(cè)試的總結(jié)

          Posted on 2009-06-22 13:39 林光炎 閱讀(2381) 評(píng)論(0)  編輯  收藏 所屬分類: JAVA

           給servlet寫(xiě)單元測(cè)試的總結(jié)收藏
          servlet的測(cè)試一般來(lái)說(shuō)需要容器的支持,不是像通常的java類的junit測(cè)試一樣簡(jiǎn)單,
           
          下面通過(guò)對(duì)HelloWorld代碼的測(cè)試闡述了幾種servlet測(cè)試方法。
           
          被測(cè)試的HelloWorld類的代碼如下:
           
          /**
           * 被測(cè)試的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為例,我總結(jié)了Servlet的多種測(cè)試方法如下:
           
          一.使用HttpUnit測(cè)試
           
          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 {

             // 創(chuàng)建Servlet的運(yùn)行環(huán)境

             ServletRunner sr = new ServletRunner();

             // 向環(huán)境中注冊(cè)Servlet

             sr.registerServlet("HelloWorld", HelloWorld.class.getName());
           
             // 創(chuàng)建訪問(wèn)Servlet的客戶端

             ServletUnitClient sc = sr.newClient();

             // 發(fā)送請(qǐng)求

             WebRequest request = new GetMethodWebRequest("http://localhost/HelloWorld");
             request.setParameter("username", "testuser");

             InvocationContext ic = sc.newInvocation(request);

             HelloWorld is = (HelloWorld) ic.getServlet();
           
             // 測(cè)試servlet的某個(gè)方法

             Assert.assertTrue(is.authenticate());

             // 獲得模擬服務(wù)器的信息

             WebResponse response = sc.getResponse(request);

             // 斷言

             Assert.assertTrue(response.getText().equals("testuser:Hello World!"));

            } catch (Exception e) {

             e.printStackTrace();

            }

           }
           
          }
           
          上述例子其實(shí)是junit的一個(gè)測(cè)試?yán)樱谄渲惺褂昧薶ttpunit模擬的servlet環(huán)境,使用上述方法測(cè)試
           
          servlet可以脫離容器,容易把該測(cè)試寫(xiě)入ant或maven腳本,讓測(cè)試進(jìn)行。
           
          httpunit網(wǎng)址:http://httpunit.sourceforge.net/
           
          使用該種方法測(cè)試的弱點(diǎn)就是:如果要使用request(response)的setCharercterEncoding方法時(shí),測(cè)試會(huì)出現(xiàn)一些問(wèn)題,
           
          而且httpunit在測(cè)試servlet行為時(shí),采用的是完全模擬瀏覽器,有時(shí)測(cè)試比較難寫(xiě)。
           
          二 使用cactus測(cè)試
           
          /**
           * cactus測(cè)試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();
               }
           
               /**
                * 測(cè)試方法測(cè)試參數(shù)在此設(shè)置
                *
                * @param webrequest
                */
           
               public void beginSaveToSessionOK(WebRequest request) {
                   request.addParameter("testparam", "it works!");
               }
              
               /**
                * 測(cè)試方法測(cè)試參數(shù)在此設(shè)置
                *
                * @param webrequest
                */
           
               public void beginDoGet(WebRequest request) {
                   request.addParameter("username", "testuser");
               }
           
               /**
                * 調(diào)用servlet的測(cè)試方法
                * 
                */

               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();
                   }
               }
           
               /**
                * 此方法可以判斷測(cè)試方法的輸出,會(huì)傳遞測(cè)試方法的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具備豐富靈活的測(cè)試功能,如要測(cè)試doGet方法,分為beginDoGet(模擬測(cè)試參數(shù)設(shè)置)、DoGet(執(zhí)行測(cè)試)、endDoGet(狀態(tài)結(jié)果驗(yàn)證)
           
          相比httpunit來(lái)說(shuō),寫(xiě)測(cè)試更為容易,測(cè)試servlet更為專業(yè),流程更為清晰,但是cactus需要容器支持,使得測(cè)試不可以自動(dòng)進(jìn)行,但是
           
          如果使用一個(gè)嵌入式的容器,測(cè)試就可以自動(dòng)了。
           
          cactus是一個(gè)servlet和jsp的測(cè)試框架:http://jakarta.apache.org/cactus/getting_started.html
           
          三 使用Jetty作為嵌入式容器測(cè)試servlet.
           
          /**
           * 一個(gè)關(guān)于嵌入式j(luò)etty測(cè)試的例子,jetty作為stubs的一個(gè)例子
           *
           */
          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 {
                //通過(guò)代碼設(shè)置并啟動(dòng)一個(gè)服務(wù)器,該服務(wù)器是servlet的測(cè)試容器
                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();
            }
           }
          }
           
          可以發(fā)現(xiàn),jetty可以充當(dāng)一個(gè)servlet的容器,方便的是,jetty支持嵌入式服務(wù),即可以通過(guò)代碼來(lái)啟動(dòng),
           
          所以要寫(xiě)自動(dòng)測(cè)試的例子很方便,可以結(jié)合httpunit或者cactus進(jìn)行servlet測(cè)試。
           
          jetty主頁(yè):http://docs.codehaus.org/display/JETTY/Embedding+Jetty


          四 使用mock對(duì)象,此處使用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,一般由容器承擔(dān),一般調(diào)用servletConfig作為參數(shù)初始化,此處模擬容器行為

                  instance.init(servletConfig);
           
                  //在某些方法被調(diào)用時(shí)設(shè)置期望的返回值,如下這樣就不會(huì)去實(shí)際調(diào)用servletConfig的getServletContext方法,而是直接返回
           
                  //servletContext,由于servletConfig是mock出來(lái)的,所以可以完全控制。

                  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();
                 
                  //以上均是錄制,下面為重放,該種機(jī)制為easymock測(cè)試機(jī)制,要理解請(qǐng)看easymock測(cè)試的一些資料
                  replay(request);
                  replay(response);
                  replay(servletConfig);
                  replay(servletContext);
           
                  instance.doGet(request, response);

                  pw.flush();
                 
           
                  //驗(yàn)證結(jié)果是否預(yù)期,如果預(yù)期,則會(huì)在pw上寫(xiě)出testuser.
                  verify(request);
                  verify(response);
                  verify(servletConfig);
                  verify(servletContext);
             }
          }
           
          mock測(cè)試注重行為,mock對(duì)象其實(shí)都是模擬的對(duì)象,方法一般直接給出一個(gè)返回值,沒(méi)有具體的對(duì)象邏輯,mock對(duì)象
           
          是用來(lái)幫助測(cè)試要測(cè)試的類的。比如要測(cè)試servlet的內(nèi)部行為,又不想要容器等環(huán)境,就可以采用mock測(cè)試。
           
          easymock是mock測(cè)試的一個(gè)框架:http://www.easymock.org/
           
          發(fā)表于 @ 2007年02月10日 22:13:00|評(píng)論(2)

          新一篇: 設(shè)計(jì)模式之創(chuàng)建模式 | 舊一篇: 服務(wù)定位器模式(service locator)wldandanpig 發(fā)表于2007年5月24日 10:09:40  IP:舉報(bào)
          請(qǐng)問(wèn)樓主
          public String saveInfo()
          {
          String reqInfo = request.getParameter("reqInfo");
          String sessInfo = (String)request.getSession().getAttribute("sessInfo");

          request.setAttribute("reqInfo" , "response:"+reqInfo);
          request.getSession().setAttribute("sessInfo", "response:"+reqInfo);

          return "SUCCESS";
          }
          這個(gè)方法怎么測(cè)試啊cz_hyf 發(fā)表于2007年5月24日 17:20:23  IP:舉報(bào)
          如果用httpunit的話

          public void testHelloWorld() {

          try {

          // 創(chuàng)建Servlet的運(yùn)行環(huán)境

          ServletRunner sr = new ServletRunner();

          // 向環(huán)境中注冊(cè)Servlet

          sr.registerServlet("HelloWorld", HelloWorld.class.getName());

          // 創(chuàng)建訪問(wèn)Servlet的客戶端

          ServletUnitClient sc = sr.newClient();

          // 發(fā)送請(qǐng)求

          WebRequest request = new GetMethodWebRequest("http://localhost/HelloWorld");
          request.setParameter("reqInfo", "......");

          InvocationContext ic = sc.newInvocation(request);

          HelloWorld is = (HelloWorld) ic.getServlet();

          // 測(cè)試servlet的某個(gè)方法

          Assert.assertEquals(is.saveInfo,"SUCCESS");

          } catch (Exception e) {

          e.printStackTrace();

          }

          }

          如果還不放心,不妨把request和request.session中的值取出來(lái)看看是否是你放進(jìn)去的


          本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/cz_hyf/archive/2007/02/10/1507211.aspx

          posts - 104, comments - 33, trackbacks - 0, articles - 0

          Copyright © 林光炎

          主站蜘蛛池模板: 峨眉山市| 谢通门县| 太湖县| 泸定县| 尼木县| 孝义市| 嘉禾县| 武定县| 玉环县| 金寨县| 崇义县| 普兰店市| 光泽县| 岳西县| 鄂尔多斯市| 台州市| 永春县| 博野县| 泽普县| 清镇市| 邵武市| 留坝县| 武城县| 瑞丽市| 固阳县| 新密市| 盐源县| 广西| 永康市| 田阳县| 雷山县| 洪洞县| 江山市| 龙门县| 敦煌市| 靖远县| 休宁县| 珲春市| 临汾市| 左云县| 讷河市|