新聞中心
隨著.NET世界中mock技術(shù)的普及,Moq也流行了起來,其部分原因是,它是專為那些剛接觸mock技術(shù)或需要編寫自定義mock對(duì)象的開發(fā)人員量身定做的類庫。Moq舍棄了經(jīng)典的Record/Reply范式,取而代之的是讓測(cè)試者使用Lambda表達(dá)式設(shè)定行為的預(yù)期結(jié)果,并使用Castle DynamicProxy來截?cái)鄊ock對(duì)象的調(diào)用。

創(chuàng)新互聯(lián)建站10多年成都企業(yè)網(wǎng)站建設(shè)服務(wù);為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計(jì)及高端網(wǎng)站定制服務(wù),成都企業(yè)網(wǎng)站建設(shè)及推廣,對(duì)成都護(hù)欄打樁機(jī)等多個(gè)行業(yè)擁有豐富的營銷推廣經(jīng)驗(yàn)的網(wǎng)站建設(shè)公司。
最近在使用的時(shí)候,當(dāng)mock對(duì)象的方法的參數(shù)帶ref關(guān)鍵字時(shí)感覺壓力很大。
首先來重現(xiàn)一下案發(fā)現(xiàn)場(chǎng),首先定義我們需要mock的接口:
- public interface ITestInterface
- {
- string TestMethodWithRef(ref string refStr, string str);
- }
接下來我們mock我們定義的接口的方法TestMethodWithRef,并指定方法被調(diào)用之后執(zhí)行委托操作:
- [TestMethod]
- public void Ref_Param_Test()
- {
- var mock = new Mock
(); - string refStr = "1";
- string str = "2";
- mock.Setup((m) => m.TestMethodWithRef(ref refStr, str)).Callback((string rs, string s) => Console.WriteLine(rs + s));
- mock.Object.TestMethodWithRef(ref refStr, str);
- mock.VerifyAll();
- }
上面的測(cè)試方法,看上去是沒什么問題,編譯也沒什么問題,但運(yùn)行測(cè)試的話悲劇發(fā)生了,拋出異常
System.ArgumentException: Invalid callback. Setup on method with parameters (String&,String) cannot invoke callback with parameters (String,String)
這異常就是說Callback委托執(zhí)行的方法的參數(shù)與Setup方法的參數(shù)對(duì)應(yīng)不起來,有人也許馬上就想說這樣改改不就行了:
- mock.Setup((m) => m.TestMethodWithRef(ref refStr, str))
- .Callback((ref string rs, string s) => Console.WriteLine(rs + s));
可惜微軟老大很直接的告訴你lamada表達(dá)式里面的參數(shù)不能用ref和out:
Variables introduced within a lambda expression are not visible in the outer method
這下子壓力真就大了,淡定,淡定,相信google!找了下還真不少信息,可惜感覺有用的就兩種解決方案。***種很直接,別用Moq偽造對(duì)象了,直接自己敲代碼偽造接口或者對(duì)象以及相關(guān)方法,但感覺這解決方案有點(diǎn)坑爹。第二種就是委托執(zhí)行的操作里面別傳參數(shù)進(jìn)去了:
- mock.Setup((m) => m.TestMethodWithRef(ref refStr, str)).Callback(() => Console.WriteLine(refStr + str)).Returns("").Verifiable();
怎么說第二種方案也還算比較滿意,至少能解決大部分問題了。
差不多這事也算完了,可惜很不小心又踩了一個(gè)坑,我們修改下我們單元測(cè)試方法:
- [TestMethod]
- public void Ref_Param_Test()
- {
- var mock = new Mock
(); - string refStr = "1";
- string str = "1";
- mock.Setup((m) => m.TestMethodWithRef(ref refStr, str)).Callback(() => { refStr = "2"; str = "2"; }).Returns("").Verifiable();
- mock.Object.TestMethodWithRef(ref refStr, str);
- mock.VerifyAll();
- Assert.AreEqual("2", str);
- Assert.AreEqual("2", refStr);
- }
直接看看這測(cè)試的邏輯,我想大部分人應(yīng)該都會(huì)覺得沒啥問題吧?
還是不放心,運(yùn)行下吧,悲劇繼續(xù)發(fā)生了,測(cè)試失?。篈ssert.AreEqual 失敗。應(yīng)為: <2>,實(shí)際為: <1>
變量refStr的值還是“1”,這下子還真有趣了!
【編輯推薦】
- c#中的數(shù)據(jù)庫訪問工廠
- C#選擇正確的集合進(jìn)行編碼
- .NET中值得體驗(yàn)的精妙設(shè)計(jì)
- ASP.NET控件10個(gè)最有用的屬性詳解
分享文章:Moq中帶ref參數(shù)方法的Callback
URL分享:http://www.fisionsoft.com.cn/article/dhdpsci.html


咨詢
建站咨詢
