使用 Moq 測試.NET Core 應用 -- Mock 方法

第一篇文章, 關於Mock的概念介紹: http://www.javashuo.com/article/p-rjikmmye-ha.htmlhtml

本文介紹使用Moq來Mock方法.git

使用的代碼: https://github.com/solenovex/Moq4-Tutorial-Code 裏面的 02 Before 部分.github

Mock 對象

緊接着上文中的例子. 上一篇文章, 我在單元測試的時候, 把依賴項設爲null:函數

而後便出現了NullReferenceException, 致使測試沒法正常運行.單元測試

首先應該作的是在TransferApproval的構造函數裏判斷參數是否爲null, 若是爲null的話應該拋出ArgumentNullException:測試

這是更恰當的異常.ui

這樣的話, 在測試的時候, 拋出的就是ArgumentNullException了, 它能夠更恰當的表達程序出現的問題:spa

 

如今咱們可使用mock版本的依賴項來代替null了:3d

上面的代碼首先使用Moq建立了一個mock版本的IPhysicalExamination的實例.調試

而因爲Moq對依賴項進行了包裝, 因此要得到實際的mock依賴項, 咱們須要使用mockExamination.Object屬性. 而這個屬性的類型就是IPhysicalExamination.

 

另一個測試方法我也這麼改一下, 然乎從新Build. Run All Tests:

仍是紅色的, 但如今是測試沒經過, 並非拋出異常.

測試沒經過的意思就是期待值和實際返回值不符.

 

讓咱們來調試一下這個測試, 我在TransferApproval類裏面設置一個端點, 查看一下這個mock依賴項的方法返回值:

 

而後調試測試:

跑到斷點

能夠看到這個Mock版本依賴項的IsHealthy()方法的返回值是false.

我並無對這個Mock版本的IPhysicalExamination的IsHealthy()方法設定返回值, 正由於如此, 它纔會返回它方法返回類型的默認值, 它的返回類型是bool, 而bool的默認值是false, 因此如今IsHealthy()方法在沒有設定的狀況下的返回值就是false.

 

It類

而PhysicalExamination這個具體的實現類因爲各類緣由致使尚未實現, 爲了讓它不妨礙咱們的單元測試, 我先設定讓它在不管傳進什麼參數的狀況下都會返回true.

從業務上來說就是假設全部轉會球員均可以經過體檢:

那麼如今全部的測試都應該能夠經過了:

 

這裏用到了It這個類, 在Moq裏, It這個類是用來作參數匹配的, it 就是"它"的意思, 它就表明須要被匹配的參數. 

It.IsAny<T>(), 它表示傳遞給方法的參數的類型只要是T就能夠, 值是任意的. 只要知足了這個條件, 那麼方法的返回值就是後邊Returns()方法裏設定的值.

 

Moq 關於It類的文檔: http://www.nudoq.org/#!/Packages/Moq/Moq/It

它有下面幾種用法:

  • Is<TValue>(Expression<Func<TValue, Boolean>>)
  • IsAny<TValue>()
  • IsIn<TValue>(IEnumerable<TValue>)
  • IsInRange<TValue>(TValue, TValue, Range)
  • IsNotIn<TValue>(IEnumerable<TValue>)
  • IsNotNull<TValue>()
  • IsRegex(string)

我認爲經過方法名就能夠知道這些方法的用途.

下面我修改一下該測試方法, 使用It其它幾個方法:

其測試結果仍然是經過的.

 

嚴謹(Strict) vs 寬鬆(Loose) Mock

Moq裏面有Strict(嚴謹)和Loose(寬鬆) mock對象的概念, 固然也有不少人不喜歡這個概念.

在當前的測試方法裏, TransferApproval依賴於Mock<IPhysicalExamination>, 並調用其IsHealthy()方法.

若是不對IsHealthy()方法進行任何設定的狀況下, 方法會返回bool的默認值false, 這種就是loose(寬鬆) Mock.

 

在建立Mock對象的時候, 還可選傳遞一個MockBehavior這個參數.

MockBehavior是一個枚舉, 它有三個值:

  • MockBehavior.Strict, 若是mock對象上的方法沒有被預先設置好, 那麼測試中調用該方法的時候就會拋出異常.
  • MockBehavior.Loose, 即便方法沒有被預先設置, 調用它的時候也不會拋出異常. 它會返回該方法返回類型的默認值.
  • MockBehavior.Default, 它表明MockBehavior.Loose.

 

若是上例使用Strict Mock, 那麼將會拋出Exception:

 

下面我把一個測試改成Strict Mock, 並取消了對IsHealthy()方法的設置:

 

而測試時會拋出MockException:

 

在對方法進行設置後, 測試就會經過:

 

能夠感受到:

Loose Mock, 能夠少寫一些設定代碼, 能夠返回默認值, 不易讓測試中斷

Strict Mock, 須要寫跟多的設定代碼, 每一個被調用的方法都須要進行設定, 因此也更容易讓測試中斷.

 

Moq的建議是: 大多數狀況下應該使用Loose Mock, 只有特殊須要的時候纔去使用Strict Mock.

 

out參數

修改一下TransferApproval類的轉會審批方法:

此次使用的是帶有out參數的IsHealthy()方法.

 

創建一個測試方法, 並設定這個帶有out參數的方法:

很簡單, 測試會經過:

 

完成的代碼在: https://github.com/solenovex/Moq4-Tutorial-Code 02 After

未完待續....

相關文章
相關標籤/搜索