給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