標籤:style blog http color 使用 strong
.Net單元測試之NMock
NMock是一款.NET平台下的基於動態代理的Mock類比對象類庫,用於C#開發。Mock對象使測試更簡單,它測試單個組件或單個類時不需要其它所有組件真正實現。也就是說我們可以僅僅只是測試一個類,NMock產生的類比是通過在運行時使用動態代理來實現的,這允許類比對象動態定義,並不需要添加任何附加的類。 通常,一個類比的實現基於被依賴的介面而建立;NMock支援對介面和類的類比,另外它還支援屬性類比。比起測試一個完整的對象關係樹更容易查清楚Bug。Mock對象一般用於以測試為驅動的開發當中。
單元測試的基本原則應該是每次只驗證一個方法,但是倘若遇到這樣一種情況:
測試方法依賴於其他一些難以操控的東西,如:網路,資料庫。或者是你測試的代碼依賴於系統的其他部分,甚至是系統的多個其他部分。在這種情況下,倘若不小心,最終可能發現自己不小心幾乎初始化了系統的每一個組件,而所有這一切只是為了給某一個測試創造必要的運行環境。這不僅花費了大量的時間,要命的是這樣的測試案例會被引入大量的耦合因素,很難到達“單元”測試的目的。我們該怎麼辦呢? 這是Mock的測試方法就派上用場了。Mock的英文的字面意思是:嘲笑,模仿,欺騙的意思。通過Mock,我們可以建立很多真實對象的替代品,在測試案例中使用它。
1) 真實的對象具有不可確定的行為(如:程式需要通過web service獲得股票的即時價格)
2) 對象很難被建立(如系統內容很難初始化)
3) 真實對象的某些行為很難被觸發(如網路錯誤,資料庫ID自增序列溢出)
4) 真實的對象令程式運行很緩慢
5) 真實對象含有UI等不方便測試的因素
6) 測試需要詢問真實對象是如何被調用的(如非同步呼叫的情況,需要驗證Callbak的函數)
7) 真實的對象目前還不存在(如依賴於其他項目組或則需要新的硬體系統)
- 進行Mock測試的步驟
- 測試代碼首先引用NMock的架構
1) 定義一個介面來描述這個對象
2) 產品代碼實現這個介面
3) 測試中Mock對象實現這個介面
下面是一個使用NMock的快速教程:
樣本 現在我們來做一個簡單的“Hello”例子,測試 Hello 類的 Greet() 方法,Hello 類依賴於一個 Person 對象,並將根據 Person 的名字向對應的帳號發送祝賀(Greet)。這個例子很簡單,其實用不到類比對象,不過用來理解 NMock 是很合適的。
public interface IPerson { string Name { get; } }然後定義具有 Greet 方法的 Hello 類,可以根據 IPerson 的名字發送祝賀資訊。public class Hello { IPerson person; public Hello(IPerson person) { this.person = person; } public String Greet() { return "Hello " + person.Name; } }
我們可以看到,Hello 類對 IPerson 介面有依賴。
在我們繼續對 Hello 類的開發之前,讓我們來學習一些關於 NMock 的基礎知識。使用 NMock 很容易根據一個給定的介面或類來建立一個類比對象;
1)首先你要執行個體化一個 Mock 對象,構建時要將你要類比的介面或類的類型傳遞給 Mock 對象作為構建參數;
2)然後,你需要記錄 Mock 對象的行為並最終通過 Mock 對象的屬性來獲得一個類比類型的樣本。下面是一個最簡單的表單的類比對象,該類比對象基於 IPerson 介面建立,沒有記錄任何行為。
//通知 NMock 你在類比哪個介面或類 IMock mockPerson = new DynamicMock(typeof(IPerson)); //擷取指定類型的一個類比執行個體 IPerson person = (IPerson) mockPerson.MockInstance;然而如果我們不記錄類比對象應該做些什麼或者在它使用之前需要做一些什麼處理,那麼實際上這個類比對象是毫無用處的;在下面的例子中,我們將記錄並設定 IPerson 的 Name 屬性的值。 //通知 NMock 你在類比哪個介面或類 IMock mockPerson = new DynamicMock(typeof(IPerson)); //設定值 mockPerson.ExpectAndReturn("Name", "John"); //擷取指定類型的一個類比執行個體 IPerson person = (IPerson) mockPerson.MockInstance; NMock 有一個很長的很有用的 Expect 方法列表,使用這些列表我們可以設定類比對象的行為,比如方法 A 被調用則返回 B,或者僅當用參數 C 調用方法 A 時才返回 B,或者當 A 方法被調用時則拋出異常 E,甚至我們可以告訴類比對象它根本就不要指望能夠調用方法 A。以上的簡單例子表明我們希望 Name 屬性只應該被調用一次,並且存取該屬性時將返回字串“John”;注意我們希望 Name 屬性只應該被調用一次,我們可以通過調用類比對象的 Verify() 方法來驗證這一點。//在類比對象上的預期檢驗 person.Verify();
這是一個簡略的預期設定的方法列表:
Expect(string methodName, object[] args)
ExpectAndReturn(string methodName, object returnVal, object[] args)
ExpectAndThrow(string methodName, Exception exceptionVal, object[] args)
ExpectNoCall(string methodName)
現在設定好所有的基本條件,我們就可以簡單的在對 Hello 類的測試中應用 NMock 了。
這就是我們的測試類別:
[TestFixture] public class HelloTest : Assertion { [Test] public void TestExpect() { //類比依賴 IMock person = new DynamicMock(typeof(IPerson)); //設定值 person.ExpectAndReturn("Name", "John"); Hello hello = new Hello((IPerson) person.MockInstance); AssertEquals("Hello John", hello.Greet()); //檢驗 Name 屬性是否只被調用了一次 person.Verify(); } }