给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可以脱离容器,容易把该测试写入antmaven脚本,让测试进行。

 

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();

         }

     }

 

     /**

      * 此方法可以判断测试方法的输出,会传递测试方法的reponseend***,并且格式化为cactus

      * WebResponse或者可以跟httpunit集成,格式化为httpunitresponse

      *

      * @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是一个servletjsp的测试框架: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);

 

        //在某些方法被调用时设置期望的返回值,如下这样就不会去实际调用servletConfiggetServletContext方法,而是直接返回

 

        //servletContext,由于servletConfigmock出来的,所以可以完全控制。

 

        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测试。

 

easymockmock测试的一个框架:http://www.easymock.org/

 

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cz_hyf/archive/2007/02/10/1507211.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值