系列目錄html
咱們前面說過.Moq在建立模擬對象的時候,簡單對象賦值默認值,引用對象賦值爲null,可是有些時候接口裏面還包含另外一個接口對象,咱們知道Moq是能夠模擬一個接口對象的,咱們能夠經過配置讓Moq模擬全部能夠Mock的對象.app
咱們新增以下代碼框架
public interface IDtoWrapper { MyDto Dto { get; set; } string GetString(); } public interface IOutString { IDtoWrapper wrapper { get; set; } }
好比咱們要模擬一個IOutString對象,若是不使用默認的行爲則裏面的wrapper對象返回爲Null,若是這樣咱們無法再繼續操做了.函數
咱們能夠對Moq的Default
行爲進行配置,讓它對IDtoWrapper對象也進行Mock測試
測試代碼以下調試
[Test] public void BehaviorConfig() { var moq = new Mock<IOutString>(); moq.DefaultValue = DefaultValue.Mock; Assert.NotNull(moq.Object.wrapper); }
以上測試會經過.這時候wrapper再也不是null,咱們即可以對其進行操做了.code
咱們經過調試能夠發現這時候不但IDtoWrapper再也不是null,它裏面的Dto屬性也被賦值爲一個new MyDto.是否是Mock框架能夠模擬一個對象呢,實際上確實是能夠,只不過是它模擬對象有不少限制,好比不能模擬不包含無參構造函數的對象,不能模擬不帶virtual或者abstract的方法等.若是咱們對模擬的對象的方法沒有virual或者abstract修飾,這時候若是進行setup則會拋出異常.htm
前面咱們講的如何經過配置使mock自動mock遇到到層級可Mock對象.這一節咱們來看另外一個問題.對象
假若有這樣一種場:要mock的接口裏有一個Name屬性,在業務層咱們要根據這個Name決定進入switch的不一樣分支裏面,可是回顧前面的章節,咱們沒有遇到這種狀況,咱們都是隻是在mock對象創建時使用setup爲要mock的對象的字段設置值.不少人可能會想,能夠經過moq對象實體的Object屬性把這個對象拿出來,而後改變它的值.咱們來看看這樣作可行不可行.blog
咱們有如下一個簡單接口
public interface ISt { string Name { get; set; } int Age { get; set; } }
測試方法以下
[Test] public void BehaviorConfig() { var moq = new Mock<ISt>(); var obj = moq.Object; obj.Name = "baidu"; Assert.NotNull(moq.Object.Name); }
咱們把moq的Object對象賦值給obj,而後經過obj改變Name值.咱們斷言moq.Object.Name的值不爲null,不幸的是,測試沒有經過.
按咱們理解obj和moq.Object應該是引用類型,因此obj值的改變會引發moq.object值的改變,然而實際狀況倒是咱們一旦把moq.Objectm賦值給了obj,它們之間便脫離了關係.看來這樣是行不通的.
如何解決這個問題呢,其實moq實例對象裏面有一個SetupProperty方法,咱們能夠經過它來顯示指定哪些屬性會被跟蹤,若是屬性被跟蹤,則它的變化就會被記錄下來,而不像上面.
[Test] public void BehaviorConfig() { var moq = new Mock<ISt>(); moq.SetupProperty(a => a.Name); var obj = moq.Object; obj.Name = "baidu"; Assert.NotNull(moq.Object.Name); }
咱們多加了一行代碼,測試即可以經過了.
可是若是屬性不少,這樣一行一行幾乎重複的代碼挺煩的,moq實例裏面還有一個SetupAllProperties
方法,這樣能夠設置全部的屬性都被跟蹤.這樣若是多條須要這個值,咱們便不須要每次都mock它,而只須要給它從新賦值便可.