Struts測試之Mock Object測試
Struts測試之Mock Object測試
以下內容引自
http://www.xgdown.com/article/239/47289_1.htm
使用Mock Object進行測試,主要是用來模擬那些在應用中不容易構造(如HttpServletRequest必須在Servlet容器中才能構造出來)或者比較復雜的對象(如JDBC中的ResultSet對象)從而使測試順利進行的工具。
JMock
簡介
請訪問
http://www.jmock.org
。
準備
1.???????
獲取
J2SDK
;
2.???????
獲取
JUnit V3.8.1
(從
http://www.junit.org
獲取開發包);
3.???????
獲取
JMock V1.0
(從
http://www.jmock.org
獲取
JMock
開發包)。
4.???????
為了開發方便,建議使用一個好
IDE
。以下例子中的代碼均是在
Eclipse V3.0
環境下進行的調試。
以下是一個簡單例子,代碼如下:
package test1;
import org.jmock.*;
import javax.servlet.http.*;
public class MockRequestTest extends MockObjectTestCase{
??? public void testMockRequest1(){
?????? //
構造一個
Mock
對象
??????? Mock mock = new Mock(HttpServletRequest.class);
???????
??????? //
設置要執行的操作,以下設置表示要調用一次
HttpServletRequest
對象的
??????? //getParameter
方法,傳遞的參數是
"name",
期望的返回是
"kongxx"
??????? mock.expects(once()).method("getParameter").with(eq("name")).will(returnValue("kongxx"));
???????
??????? //
根據
Mock
對象獲取一個
HttpServletRequest
對象
??????? HttpServletRequest request = (HttpServletRequest)mock.proxy();
???????
??????? //
斷言調用結果
??????? assertEquals("kongxx" ,request.getParameter("name"));???????
??? }
??? public void testMockRequest2(){
?????? //
構造一個
Mock
對象
??????? Mock mock = new Mock(HttpServletRequest.class);
???????
??????? //
設置要執行的操作,以下設置表示要調用一次
HttpServletRequest
對象的
??????? //getParameter
方法,傳遞的參數是
"name",
期望的返回是
"kongxx"
??????? mock.expects(once()).method("getParameter").with(eq("name")).will(returnValue("kongxx"));
???????
??????? //
根據
Mock
對象獲取一個
HttpServletRequest
對象
??????? HttpServletRequest request = (HttpServletRequest)mock.proxy();
???????
??????? //
調用
HttpServletRequest
對象的方法
??????? request.getParameter("name");???????
???????
??????? //
驗證執行結果
??????? mock.verify();
??? }
}
|
編譯并將其當做一個
Test Case
運行,會發現兩個測試方法均測試成功。
MyClass
需要測試的類,提供了兩個方法
getName
和
getPassword
,都使用
HttpServletRequest
作為輸入參數并返回從
HttpServletRequest
中取得的參數,具體代碼如下:
package test2;
import javax.servlet.http.*;
public class MyClass {
??? public String getName(HttpServletRequest request) {
?????? return request.getParameter("name");
??? }
???
??? public String getPassword(HttpServletRequest request) {
?????? return request.getParameter("password");
??? }
} |
TestMyClass
測試類,其中構造了一個假的
HttpServletRequest
對象,用來測試
MyClass
中的
getName
和
getPassword
方法,代碼如下:
package test2;
import org.jmock.*;
import javax.servlet.http.*;
public class TestMyClass extends MockObjectTestCase{
??? private MyClass myclass ;
??? private Mock mockRequest ;
??? private HttpServletRequest request ;
???
??? public void setUp() {??????
?????? myclass = new MyClass();
??????
?????? //
構造一個
Mock
對象
?????? mockRequest = new Mock(HttpServletRequest.class);
??????
?????? //
根據
Mock
對象獲取一個
HttpServletRequest
對象
?????? request = (HttpServletRequest)mockRequest.proxy();
??? }
??? public void tearDown() {
?????? //TODO
??? }
??? public void testGetName(){
?????? //
設置要執行的操作,以下設置表示要調用一次
HttpServletRequest
對象的
??????? //getParameter
方法,傳遞的參數是
"name",
期望的返回是
"kongxx"?????
?????? mockRequest.expects(atLeastOnce()).method("getParameter").with(eq("name")).will(returnValue("kongxx"));
??????
?????? assertNotNull(myclass.getName(request));
??????? assertEquals("kongxx" ,myclass.getName(request));??????
??? }
??? public void testGetPassword(){
?????? //
設置要執行的操作,以下設置表示要調用一次
HttpServletRequest
對象的
??????? //getParameter
方法,傳遞的參數是
"password",
期望的返回是
"123456789" ?
???
??? mockRequest.expects(atLeastOnce()).method("getParameter").with(eq("password")).will(returnValue("123456789"));
??????
?????? assertNotNull(myclass.getPassword(request));
??????? assertEquals("123456789" ,myclass.getPassword(request));
??? }
} |
編譯并將其當做一個
Test Case
運行,會發現兩個測試方法均測試成功。
EasyMock
簡介
請訪問
http://www.easymock.org
。
準備
1.
???????
獲取
J2SDK
;
2.
???????
獲取
JUnit V3.8.1
(從
http://www.junit.org
獲取開發包);
3.
???????
獲取
EasyMock V1.1
(從
http://www.easymock.org
獲取
EasyMock
開發包)。
4.
???????
為了開發方便,建議使用一個好
IDE
。以下例子中的代碼均是在
Eclipse V3.0
環境下進行的調試。
例子一
以下是一個簡單例子,為了方便對比,這里重新實現了
JMock
例子一
,代碼如下:
package test1;
import org.easymock.*;
import junit.framework.*;
import javax.servlet.http.*;
public class MockRequestTest extends TestCase{
??? private MockControl control;
??? private HttpServletRequest mockRequest;
??? public void testMockRequest(){
?????? //
創建一個
Mock HttpServletRequest
的
MockControl
對象
?????? control = MockControl.createControl(HttpServletRequest.class);
??????
?????? //
獲取一個
Mock HttpServletRequest
對象
?????? mockRequest = (HttpServletRequest) control.getMock();
??????????
?????? //
設置期望調用的
Mock HttpServletRequest
對象的方法
?????? mockRequest.getParameter("name");
??????
?????? //
設置調用方法期望的返回值,并指定調用次數
?????? //
以下后兩個參數表示最少調用一次,最多調用一次
?????? control.setReturnValue("kongxx" ,1 ,1);??
??????
?????? //
設置
Mock HttpServletRequest
的狀態,
?????? //
表示此
Mock HttpServletRequest
對象可以被使用
?????? control.replay();
??????
?????? //
使用斷言檢查調用
?????? assertEquals("kongxx",mockRequest.getParameter("name"));
??????
?????? //
驗證期望的調用
?????? control.verify();
??? }
}
|
編譯并將其當做一個
Test Case
運行,會發現兩個測試方法均測試成功。
例子二
同例子一樣,對
JMock
例子二
重新實現產生了
EasyMock
的例子二。
需要測試的類代碼如下:
package test2;
import javax.servlet.http.*;
public class MyClass {
??? public String getName(HttpServletRequest request) {
?????? return request.getParameter("name");
??? }
???
??? public String getPassword(HttpServletRequest request) {
?????? return request.getParameter("password");
??? }
}
|
測試類代碼如下:
package test2;
import org.easymock.*;
import junit.framework.*;
import javax.servlet.http.*;
public class TestMyClass extends TestCase{
???
??? private MockControl control;
??? private HttpServletRequest mockRequest;
??? private MyClass myclass ;
???
??? public void setUp() {??????
?????? myclass = new MyClass();
??????
?????? //
創建一個
Mock HttpServletRequest
的
MockControl
對象
?????? control = MockControl.createControl(HttpServletRequest.class);
??????
?????? //
獲取一個
Mock HttpServletRequest
對象
?????? mockRequest = (HttpServletRequest) control.getMock();??????
??? }
??? public void tearDown() {
?????? //TODO
??? }
??? public void testGetName(){
?????? //
設置期望調用的
Mock HttpServletRequest
對象的方法
?????? mockRequest.getParameter("name");
??????
?????? //
設置調用方法期望的返回值,并指定調用次數
?????? //
以下后兩個參數表示最少調用一次,最多調用一次
?????? control.setReturnValue("kongxx" ,1 ,2);??
??????
?????? //
設置
Mock HttpServletRequest
的狀態,
?????? //
表示此
Mock HttpServletRequest
對象可以被使用
?????? control.replay();
??????
?????? //
使用斷言檢查調用
?????? assertNotNull(myclass.getName(mockRequest));
?????? assertEquals("kongxx",myclass.getName(mockRequest));
??????
?????? //
驗證期望的調用
?????? control.verify();???
??? }
??? public void testGetPassword(){
?????? //
設置期望調用的
Mock HttpServletRequest
對象的方法
?????? mockRequest.getParameter("password");
??????
?????? //
設置調用方法期望的返回值,并指定調用次數
?????? //
以下后兩個參數表示最少調用一次,最多調用一次
?????? control.setReturnValue("kongxx" ,1,2);
??????
?????? //
設置
Mock HttpServletRequest
的狀態,
?????? //
表示此
Mock HttpServletRequest
對象可以被使用
?????? control.replay();
??????
?????? //
使用斷言檢查調用
?????? assertNotNull(myclass.getPassword(mockRequest));
?????? assertEquals("kongxx",myclass.getPassword(mockRequest));
??????
?????? //
驗證期望的調用
?????? control.verify();??
??? }
}
|
編譯并將其當做一個
Test Case
運行,會發現兩個測試方法均測試成功。
獨立測試就是單獨測試一個類或方法里的代碼,而不測試里面調用的其他類或方法的代碼。即假定調用的其他類或方法都正常執行。
- 實際對象的行為還不確定。
- 實際的對象創建和初始化非常復雜。
- 實際對象中存在很難執行到的行為(如網絡異常等)。
- 實際的對象運行起來非常的慢。
- 實際對象是用戶界面程序。
- 實際對象還沒有編寫,只有接口等。
假定我們有對象A,它內部頻繁調用了B中的方法。但是除了調用B的部分還存在自己的邏輯代碼。這時,我們只想寫A的單體測試,而不想測試B(因為B可能還沒編寫,只寫了實現的接口或者B運行太慢了影響我們的測試效率)。這樣的話,我們就需要創建B的Mock對象。
換言之,我們現在不關心B,我們假定B的行為都能正常運行。我們的目標是假定B運行正常的情況下,來對A進行單體測試。
Mock對象就是我們先不用關心的對象,但是我們的關注對象對它有調用,所以我們給關注對象準備個假貨讓它用。
?
posted on 2006-02-17 09:02 扭轉乾坤 閱讀(544) 評論(0) 編輯 收藏 所屬分類: Struts相關