初學 Moq


 

1.什么是Moq?

 Moq是一個針對.Net開發的模擬庫,它從開始就充分利用了(Linq表達式)和(Lambda表達式)。它的目標是讓模擬以一種自然的方式與現有單元測試進行集成,使它更加簡單、直觀。使它成為了一個高生產力、類型安全、重構友好的模擬庫。

2.從哪得到Moq?

可以直接使用VS中的插件Nuget來獲取Moq並且引用到指定的項目。

 

 

3.Moq原理:

Moq使用Castle DynamicProxy完成這個任務。基本原理就是它利用反射機制的Emit功能動態生成一個空類型(也就是所有接口的方法都實例化,但是沒有任何功能,只是一個程序骨架)。所以Mock的能力就在於可以利用DynamicProxy的機制快速生產出一個假對象來,用於模仿真對象的行為。

4.Moq中的重要成員

(1).Mock:通過這個類,我們可以得到一個Mock<T>對象。T可以是接口,也可以是類。它有一個PublicVirtual屬性。比如:

定義一個接口界面:

public interface ITest
        {

            bool DoSomething(string actionname);

        }

定義測試方法:

 [TestMethod]
        public void Test_Interface_ITest()
        {
            //創建Mock對象,偽造一個ITest的實現
            var mo = new Mock<ITest>();
            //設置模擬對象
            mo.Setup(foo => foo.DoSomething("Ping")).Returns(true);(注意:Setup方法的參數是一個lambda表達式:可以這樣理解:當被模擬的對象foo調用它自己的方法Dosomething(),並且參數是Pring。添加后綴名Return(true)可以這樣理解:前邊的請求返回結果為真。這是指定的返回值。當一個請求調用DoSomething()方法時。如果傳入的參數是Pring,那么就返回true。然后添加一個斷言,去判斷是否能得到預期結果)

            //斷言它
            Assert.AreEqual(true, mo.Object.DoSomething("Ping"));

      }

(2).It:這是一個靜態類,定義了靜態的泛型方法:

Is<TValue>IsAny<TValue>IslnRange<TValue>IsRegex。去過濾參數。

(3)MockBehavior:這個類用於模擬對象的行為。就像是否按照默認的模式去模擬

(4)Verification:有時候,我們要確定一個方法是否被調用了,或者甚至要知道它被調用了多少次。就使用Verify()方法。;例如:

mock.Verify(foo=>foo.DoSomething(Pring),Times.Once())

上邊的代碼嘗試驗證DoSomething(Pring)需要被調用,並且只調用一次。出了Once選項,也有更多的選項可以選擇:如:Atleast(至少)AtLeastonce(至少一次),AtMost(最多),AtMostOnce(最多一次),Between(之間),Equals(等於),Exactly(確切的),Never(從未)Once(一次)

5.功能點介紹

(1).帶有引用或輸出參數的方法。例如:

{方法:string GetAddress(string strUser, out string Address);

string GetFamilyCall(ref string strUser);}定義兩個方法
var customer = new Mock<ITest>();創建Mock對象,偽造一個ITest的實現

var outString="oo";

customer.Setup(p => p.GetAddress("", out outString)).Returns("sichuan");

customer.Setup(p => p.GetFamilyCall(ref outString)).Returns("xx");

(2)調用方法時拋出異常

方法:void ShowException(string str);

測試:var customer = new Mock<ITest>();

customer.Setup(p => p.ShowException(string.Empty))

.Throws(new Exception("參數不能為空!"));

customer.Object.ShowException("");

(3)Is<T>:匹配確定的給定類型

customer.Setup(x => x.SelfMatch(It.Is<int>(i => i % 2 == 0))).Returns("1");

方法SelfMatch接收int型的參數,當參數為偶數時,才返回字符串1.

(4)IsAny<T>:匹配給定的任何值

customer.Setup(p => p.SelfMatch(It.IsAny<int>())).Returns((int k) => "任何數:" + k);

方法SelfMatch接收int型,且任何int型參數都可以,然后返回:任何數:”+K.

(5)IsInRange<T>:匹配給定類型的范圍

customer.Setup(p => p.SelfMatch(It.IsInRange<int>(0, 10, Range.Inclusive))).Returns("10以內的數");

方法SelfMatch接受int型,且當范圍在[0,10]時,才返回10以內的數

其中,這個方法,帶有一個包含與排除開關。

(6)IsRegex<T>:正則匹配

customer.Setup(p => p.ShowException(It.IsRegex(@"^\d+$")))

.Throws(new Exception("不能是數字"));

(7)Callbacks回調函數

當執行某方法時,調用其內部輸入的(Action)委托,有它的5種重載:

Callback(Action)

Callback<T>(Action<T>)

Callback<T1, T2>(Action<T1, T2>)

Callback<T1, T2, T3>(Action<T1, T2, T3>)

Callback<T1, T2, T3, T4>(Action<T1, T2, T3, T4>)

這個方法調用其內部輸入的Action委托,Aciton<T>5種重載,所以這里的Callbacks5種重載。

(8).Verify驗證

用於測試mock對象的方法或屬性是否被調用執行.也有很多重載:

Verify()

Verify(Expression<Action<T>>)

Verify<TResult>(Expression<Func<T, TResult>>)

Verify(Expression<Action<T>>, Times)

Verify(Expression<Action<T>>, String)

Verify<TResult>(Expression<Func<T, TResult>>, Times)

Verify<TResult>(Expression<Func<T, TResult>>, String)

Verify(Expression<Action<T>>, Times, String)

Verify<TResult>(Expression<Func<T, TResult>>, Times, String)

(9).VerifyAll驗證

在使用Verify方法時,只有被標記為可證實的(.Verifiable())的才可以驗證。

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM