使用 Moq 測試.NET Core 應用 -- Mock 屬性

solenovex發表於2018-07-13

第一篇文章, 關於Mock的概念介紹: https://www.cnblogs.com/cgzl/p/9294431.html

第二篇文章, 關於方法Mock的介紹: https://www.cnblogs.com/cgzl/p/9300356.html

本文介紹Moq的使用.

使用的程式碼: https://github.com/solenovex/Moq4-Tutorial-Code 裡面的 03 Before 部分.

Mock屬性

屬性是指 get set property.

接著上文, 我在03 Before部分的程式碼裡做了一些修改.

首先IPhysicalExamination介面新增了IsMedicalRoomAvailable屬性:

其實現類:

屬性方法內依然沒有做實現.

 

新增的這個屬性在業務上的意思就是體檢室是否可以使用. 如果不可以使用的話, 那麼球員的轉會操作應該被推遲.

所以還需要為轉會結果列舉新增一個推遲:

 

最後在轉會審批邏輯裡進行判斷, 如果體檢室不可用, 那麼轉會就被推遲:

 

在單元測試裡對屬性進行mock非常的簡單:

 

這個測試也會通過的:

 

遞迴Mock

修改一下IPhysicalExamination介面, 形成一個多層巢狀的屬性:

IPhysicalExamination --> IMedicalRoom --> IMedicalRoomStatus --> IsAvailable.

通過上面這一串來判斷體檢室是否可用.

 

相應的實現類也要修改:

 

轉會審批方法裡也要修改:

 

而在單元測試的方法裡, 肯定是報錯的:

 

按照正常的思路, 我們可能會這樣做:

就是從內到外一層一層的mock.

這麼做是沒問題的, 測試也會通過:

 

但是這樣做很麻煩, 而Moq則提供了一種簡單的方式來處理這種多層的/遞迴的mock:

這樣寫即可. 測試同樣會通過:

 

為屬性設定預設值

但是, 問題來了, 我還有一些其它的單元測試方法, 它們也需要用到這個屬性, 現在它們的狀態是:

有的測試失敗是因為其MockBehavior是Strict的, 而其它的失敗則是因為裡面出現了NullReferenceException.

 

針對這些情況, 我們可以這樣設定:

這樣設定之後, 它會返回屬性型別的預設值, 因為我沒有設定返回值.

雖然測試依然不通過, 這是因為邏輯上的問題, 而不會丟擲異常:

 

針對這種情況, 還有一種更好的辦法. 我們可以為mock物件設定預設值:

把DefaultValue的值設為DefaultValue.Mock.

但是DefaultValue這個屬性只對引用型別起作用(對值型別不起作用), 像這種遞迴的mock, 它會遞迴的建立所需的引用型別, 但是最後的IsAvailable這個值型別是不起作用的.

測試:

因為最後一層是bool型別的, 是值型別, 所以上面的設定不起作用, 返回的是false. 所以測試沒通過.

 

那我就把它改成string型別好了:

審批方法:

然後再除錯測試:

string是引用型別, 但是mock的值依然是null...??!!??

這是因為string是一個sealed class, 而DefaultValue.Mock只對介面, 抽象類和非sealed的class起作用....

不過測試仍然是可以通過的, 因為我改邏輯了:

 

注意, 這個預設值只對寬鬆(Loose) mock, 起作用.針對Strict mock, 仍然需要設定最後一層屬性的值.

 

屬性值變化跟蹤

需要新增一些程式碼, 首先新增一個列舉:

為介面新增屬性:

實現類:

然後在審批類裡, 我設定了這個屬性的值:

 

上面的程式碼也就是說, 我的mock物件的某個屬性在測試的時候它的值會發生變化. 而Moq可以記住這些mock屬性的變化的值.....

 

新寫一個測試:

這裡使用mockObj.SetupProperty()方法來開始追蹤屬性. 這個測試會通過:

該方法也可以通過下面的寫法來為被追蹤的屬性設定預設值:

mockExamination.SetupProperty(x => x.PhysicalGrade, PhysicalGrade.Failed);.

 

如果這個物件上有很多屬性需要進行設定和追蹤, 那麼可以使用:

mock.SetupAllProperties(); 這個方法:

 

注意, 這個方法應該最先呼叫, 否則的話其它的設定可能會被覆蓋.

 

本文完成的程式碼在: https://github.com/solenovex/Moq4-Tutorial-Code 裡面的03 After.

未完待續......

相關文章