給servlet寫單元測試的總結

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

           給servlet寫單元測試的總結收藏
          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/
           
          發表于 @ 2007年02月10日 22:13:00|評論(2)

          新一篇: 設計模式之創建模式 | 舊一篇: 服務定位器模式(service locator)wldandanpig 發表于2007年5月24日 10:09:40  IP:舉報
          請問樓主
          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";
          }
          這個方法怎么測試啊cz_hyf 發表于2007年5月24日 17:20:23  IP:舉報
          如果用httpunit的話

          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("reqInfo", "......");

          InvocationContext ic = sc.newInvocation(request);

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

          // 測試servlet的某個方法

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

          } catch (Exception e) {

          e.printStackTrace();

          }

          }

          如果還不放心,不妨把request和request.session中的值取出來看看是否是你放進去的


          本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/cz_hyf/archive/2007/02/10/1507211.aspx

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

          Copyright © 林光炎

          主站蜘蛛池模板: 姚安县| 故城县| 牙克石市| 宣威市| 吴旗县| 中江县| 崇礼县| 淮南市| 揭东县| 西乌| 岱山县| 长沙市| 巫溪县| 道真| 普洱| 塔河县| 正镶白旗| 虎林市| 昌黎县| 屯门区| 八宿县| 项城市| 望城县| 镶黄旗| 尼玛县| 昆明市| 上饶县| 河西区| 陆川县| 内丘县| 东莞市| 大埔区| 连州市| 类乌齐县| 康平县| 开封县| 青铜峡市| 侯马市| 黑山县| 乳山市| 内江市|