測(cè)試方法
?1?//??準(zhǔn)備?Mock?IFoo?接口??2?var?mock??=???new??Mock?<?IFoo?>?();
?3?//??配置準(zhǔn)備模擬的方法猬仁,當(dāng)調(diào)用接口中的?DoSomething?方法逐虚,并傳遞參數(shù)?"bing"?的時(shí)候叭爱,返回?true??4?mock.Setup(foo??=>??foo.DoSomething(?"?ping?"?)).Returns(?true?);
?5??6?//?方法的參數(shù)中使用了?out?參數(shù)
?7?//??out?arguments???8?var?outString??=???"?ack?"?;
?9?//??當(dāng)調(diào)用?TryParse?方法的時(shí)候买雾,out?參數(shù)返回?"ack",?方法返回?true,?lazy?evaluated??10?mock.Setup(foo??=>??foo.TryParse(?"?ping?"?,??out??outString)).Returns(?true?);
11?12?//??ref?參數(shù)?13?var?instance??=???new?Bar();
14?//??僅僅在使用?ref?調(diào)用的時(shí)候漓穿,才會(huì)匹配下面的測(cè)試?15?mock.Setup(foo??=>??foo.Submit(?ref??instance)).Returns(?true?);
16?17?//?當(dāng)方法返回值得時(shí)候晃危,還可以訪問(wèn)返回的值
18?//??這里可以使用多個(gè)參數(shù)?19?mock.Setup(x??=>??x.DoSomething(It.IsAny?<?string?>?()))
20??????????????????.Returns((?string??s)??=>?s.ToLower());
21?22?//??在被調(diào)用的時(shí)候拋出異常?23?mock.Setup(foo??=>??foo.DoSomething(?"?reset?"?)).Throws?<?InvalidOperationException?>();
24?mock.Setup(foo??=>??foo.DoSomething(?""?)).Throws(?new??ArgumentException(?"?command?"?);
25?26?//??延遲計(jì)算返回的結(jié)果??27?mock.Setup(foo??=>??foo.GetCount()).Returns(()??=>?count);
28?29?//??在每一次調(diào)用的時(shí)候僚饭,返回不同的值??30?var?mock??=???new??Mock?<?IFoo?>?();
31?var?calls??=???0?;
32?mock.Setup(foo??=>?foo.GetCountThing())
33??????.Returns(()??=>?calls)
34??????.Callback(()??=>??calls?++?);
35?36?//??第一次調(diào)用返回?0苇瓣,?下一次是?1偿乖,?依次類推?37?Console.WriteLine(mock.Object.GetCountThing());
匹配參數(shù)
?1?//??任意值???2?mock.Setup(foo??=>??foo.DoSomething(It.IsAny?<?string?>?())).Returns(?true?);
?3??4?//??提供的值必須匹配一個(gè)函數(shù),?lazy?evaluated???5?mock.Setup(foo??=>??foo.Add(It.Is?<?int?>?(i??=>??i??%???2???==???0?))).Returns(?true?);
?6??7?//??匹配一個(gè)范圍???8?mock.Setup(foo??=>??foo.Add(It.IsInRange?<?int?>?(?0?,??10?,?Range.Inclusive))).Returns(?true);
?9?10?//??匹配正則表達(dá)式?11?mock.Setup(x??=>??x.DoSomething(It.IsRegex(?"?[a-d]+?"?,?RegexOptions.IgnoreCase))).Returns(?"?foo?"?);
屬性
?1?//??普通屬性??2?mock.Setup(foo??=>??foo.Name).Returns(?"?bar?"?);
?3??4?//??多層的屬性??5?mock.Setup(foo??=>??foo.Bar.Baz.Name).Returns(?"?baz?"?);
?6??7?//??期望設(shè)置屬性的值為?"foo"???8?mock.SetupSet(foo??=>??foo.Name??=???"?foo?"?);
?9?10?//??或者直接驗(yàn)證賦值??11?mock.VerifySet(foo??=>??foo.Name??=???"?foo?"?);
設(shè)置屬性媳禁,以便自動(dòng)跟蹤它的值
?1?//??開(kāi)始?"tracking"?屬性的?sets/gets???2?mock.SetupProperty(f??=>?f.Name);
?3??4?//??提供一個(gè)默認(rèn)的值??5?mock.SetupProperty(f??=>??f.Name,??"?foo?"?);
?6??7?//??現(xiàn)在损话,你可以:????8?IFoo?foo??=?mock.Object;
?9?10?//??保存的值??11?Assert.Equal(?"?foo?"?,?foo.Name);
12?13?//??重新設(shè)置一個(gè)值?14?foo.Name??=???"?bar?"?;
15?Assert.Equal(?"?bar?"?,?foo.Name);
還可以準(zhǔn)備所有的屬性
mock.SetupAllProperties();
事件
?1?//??拋出一個(gè)事件???2?mock.Raise(m??=>??m.FooEvent??+=???null?,??new?FooEventArgs(fooValue));
?3??4?//??多層的后代中的事件???5?mock.Raise(m??=>??m.Child.First.FooEvent??+=???null?,??new?FooEventArgs(fooValue));
?6??7?//??當(dāng)?Submit?方法被調(diào)用的時(shí)候,拋出一個(gè)事件???8?mock.Setup(foo??=>??foo.Submit()).Raises(f??=>??f.Sent??+=???null?,?EventArgs.Empty);
?9?10?//?拋出異常將會(huì)觸發(fā)對(duì)象底層的行為
11?//?你可能需要在后面進(jìn)行斷言處理
12?13?//??拋出一個(gè)自定義的事件?14?public???delegate???void??MyEventHandler(?int??i,??bool?b);
15?public???interface??IFoo?{????event?MyEventHandler?MyEvent;??}
16?var?mock??=???new??Mock?<?IFoo?>?();
17?...
18?19?//??傳遞自定義的事件參數(shù)?20?mock.Raise(foo??=>??foo.MyEvent??+=???null?,??25?,??true?);
?回調(diào)
?1?var?mock??=???new??Mock?<?IFoo?>?();
?2?mock.Setup(foo??=>??foo.Execute(?"?ping?"?))
?3??????.Returns(?true?)
?4??????.Callback(()??=>??calls?++?);
?5??6?//??使用調(diào)用的參數(shù)???7?mock.Setup(foo??=>??foo.Execute(It.IsAny?<?string?>?()))
?8??????.Returns(?true?)
?9??????.Callback((?string??s)??=>?calls.Add(s));
10?11?//??使用泛型語(yǔ)法??12?mock.Setup(foo??=>??foo.Execute(It.IsAny?<?string?>?()))
13??????.Returns(?true?)
14??????.Callback?<?string?>?(s??=>?calls.Add(s));
15?16?//??使用多個(gè)參數(shù)?17?mock.Setup(foo??=>??foo.Execute(It.IsAny?<?int?>?(),?It.IsAny?<?string?>?()))
18??????.Returns(?true?)
19??????.Callback?<?int?,??string?>?((i,?s)??=>?calls.Add(s));
20?21?//??調(diào)用之前和之后的回調(diào)??22?mock.Setup(foo??=>??foo.Execute(?"?ping?"?))
23??????.Callback(()??=>??Console.WriteLine(?"?Before?returns?"?))
24??????.Returns(?true?)
25??????.Callback(()??=>??Console.WriteLine(?"?After?returns?"?));
驗(yàn)證
?1?mock.Verify(foo??=>??foo.Execute(?"?ping?"?));
?2??3?//??在驗(yàn)證失敗的時(shí)候,提供自定義的錯(cuò)誤提示信息???4?mock.Verify(foo??=>??foo.Execute(?"?ping?"?),??"?When?doing?operation?X,?the?service?should?be?pinged?always?"?);
?5??6?//??從沒(méi)有被調(diào)用的方法???7?mock.Verify(foo??=>??foo.Execute(?"?ping?"?),?Times.Never());
?8??9?//??至少調(diào)用過(guò)一次??10?mock.Verify(foo??=>??foo.Execute(?"?ping?"?),?Times.AtLeastOnce());
11?mock.VerifyGet(foo??=>?foo.Name);
12?13?//??驗(yàn)證對(duì)屬性的賦值.??14?mock.VerifySet(foo??=>?foo.Name);
15?16?//??驗(yàn)證對(duì)于屬性設(shè)置特定的值??17?mock.VerifySet(foo??=>??foo.Name??=?"?foo?"?);
18?19?//??驗(yàn)證匹配的參數(shù)??20?mock.VerifySet(foo??=>??foo.Value??=??It.IsInRange(?1?,??5?,?Range.Inclusive));
?自定義 Mock 行為
Mock 的行為分為嚴(yán)格的 Strict 和寬松的 Loose, 默認(rèn)為寬松的债沮。在嚴(yán)格模式下疫衩,使用任何沒(méi)有被指定的行為闷煤,都將會(huì)拋出異常鲤拿,寬松模式下,不會(huì)拋出任何異常,方法將會(huì)返回默認(rèn)值或者空的數(shù)組等等久锥。
var?mock??=???new??Mock?<?IFoo?>?(MockBehavior.Strict);
如果沒(méi)有重寫基類的實(shí)現(xiàn),默認(rèn)將不會(huì)調(diào)用基類冤寿,在 Mock Web/Html 控件的是必須的督怜。
var?mock??=???new??Mock?<?IFoo?>??{?CallBase??=???true??};
?創(chuàng)造自動(dòng)遞歸的 Mock, Mock 對(duì)象對(duì)于它的任何成員將會(huì)返回一個(gè)新的 Mock 對(duì)象号杠。
var?mock??=???new??Mock?<?IFoo?>??{?DefaultValue??=?DefaultValue.Mock?};
//?默認(rèn)是?DefaultValue.Empty
//??現(xiàn)在這個(gè)屬性將會(huì)返回一個(gè)新的?Mock?對(duì)象??IBar?value??=?mock.Object.Bar;
//?可以使用返回的?Mock?對(duì)象,?后即對(duì)屬性的訪問(wèn)返回相同的對(duì)象實(shí)例
//?這就允許我們可以進(jìn)行后繼的設(shè)置
//??set?further?expectations?on?it?if?we?want??var?barMock??=?Mock.Get(value);
barMock.Setup(b
?=>??b.Submit()).Returns(?true?);
中心化的 Mock 實(shí)例創(chuàng)建和管理:你可以在一個(gè)地方使用 MockRepository 創(chuàng)建和驗(yàn)證所有的 Mock 對(duì)象,設(shè)置 MockBehavior, CallBse 和 DefaultValue 約束眼溶。
var?factory??=???new??MockFactory(MockBehavior.Strict)?{?DefaultValue??=?DefaultValue.Mock?};
//??創(chuàng)建?Mock?對(duì)象?var?fooMock??=??factory.Create?<?IFoo?>?();
//??在創(chuàng)建的時(shí)候重寫倉(cāng)庫(kù)的設(shè)置??var?barMock??=??factory.Create?<?IBar?>?(MockBehavior.Loose);
//??驗(yàn)證通過(guò)倉(cāng)庫(kù)創(chuàng)建的對(duì)象??factory.Verify();
其它
//??用在測(cè)試用例的開(kāi)始??using?Moq.Protected()
//??測(cè)試中?var?mock??=???new??Mock?<?CommandBase?>?();?mock.Protected()
.Setup
?<?int?>?(?"?Execute?"?)
.Returns(
?5?);
//?如果用到了參數(shù)匹配,?必須使用?ItExpr?來(lái)代替?It
//??以后計(jì)劃改進(jìn)?mock.Protected()
.Setup
?<?string?>?(?"?Execute?"?,?????????ItExpr.IsAny?<?string?>?())
.Returns(
?true?);
高級(jí)特性
?1?//??從?Mock?實(shí)例重新獲得?Mock?對(duì)象??2?IFoo?foo??=???//??get?mock?instance?somehow???3?var?fooMock??=?Mock.Get(foo);
?4?fooMock.Setup(f??=>??f.Submit()).Returns(?true?);
?5??6?//??實(shí)現(xiàn)多個(gè)接口???7?var?foo??=???new??Mock?<?IFoo?>?();
?8?var?disposableFoo??=??foo.As?<?IDisposable?>?();
?9?10?//?現(xiàn)在?IFoo?mock?已經(jīng)實(shí)現(xiàn)了接口?IDisposable?:)?disposableFoo.Setup(df?=>?df.Dispose());
11?12?//??定制匹配??13?mock.Setup(foo??=>??foo.Submit(IsLarge())).Throws?<?ArgumentException?>?();?...
14?public???string?IsLarge()
15?{
16??????return??Match?<?string?>?.Create(s??=>???!?String.IsNullOrEmpty(s)??&&??s.Length??>???100);
17?}