少年阿賓

          那些青春的歲月

            BlogJava :: 首頁 :: 聯系 :: 聚合  :: 管理
            500 Posts :: 0 Stories :: 135 Comments :: 0 Trackbacks

          手頭的項目越來越大,很多以前不會出現的問題開始浮現。

           

          比如:我修改了一個基礎的類庫,卻意外的影響了九重天外的客戶項目,直接導致一個功能無法實現。我郁悶?。。?!

           

          因此開始要有組織、有預謀、有計劃的對項目過程進行測試驅動了。最終目標是,我修改了底層某個dll的某個方法,測試框架能夠自動幫我找出來所有收到影響的類,全部執行一次回歸測試,并發送一份漂亮的報告到我手里。

           

          這個目標估計1、2個星期才能實現,不過現在先放出一個非常漂亮的MOCK核心代碼。 

           

          研究過程

          在不斷收集各種資料過程中,學習了很多,例如以下關鍵字,有興趣的兄弟可以自己搜索一下:

           

          testdriven.net, nunit,  typemock, cruiseControl.net, Confluence, JIRE, NUnitForms, WatiN, MBUnit, CSUnit, NBehave, Gallio

          ranorex,  dynamicProxy...

           

          估計各位有時間看看上面的簡介,就能夠掌握現在測試驅動的大致發展。

           

          1. nunit的核心代碼非常容易理解,大伙自己下載看看就行了。
          2. testdriven.net 的前身是:NUnitAddin, 如果要研究如何testdriven集成到vs,看看不錯。
          3. WatiN的核心代碼雖然我沒有看,不過猜也能猜到,就是調用了IE的核,然后搜索上面的html標簽操作。
          4. typeMock有點混蛋,源碼混淆了,無法拿到核心技術,不過從介紹來看是源自了castle.DynamicProxy,那么各位可以參觀一下一篇非常垃圾的文章,但是起碼讓我入門了: http://www.cublog.cn/u/23701/showart_1414436.html
          5. 最后,我來到了Moq,開始因為聽說是.net3.5,就沒有看源碼,不過剛才研究了一下頓時非常興奮。起碼Moq能讓我解決了50%的工作。

           

          接下來就說下Mock技術和測試驅動中的作用。

           

          Mock技術 

          我最不喜歡老外造名詞,所以會用自己的體會去介紹。

          mock的本質就是模擬目標對象的一個假對象。 

          這個性質在測試驅動中非常有用,例如我的代碼是:

          代碼
                  public DateTime GetNextFiredDate(DateTime now, IOrmScheduleTrigger trigger, int triggeredtimes)
                  {
                      
          return GetNextFiredDate(now, trigger.TriggerType, trigger.TriggerExpression, triggeredtimes);
                  }

           

           

           現在要測試這個代碼,就需要傳入一個IOrmScheduleTrrigger的接口對象。但是不幸的是,這個對象是個ORM,要啟動這個對象,就涉及到了數據庫。。。。

           

          老大,我只是想測試一下一輛寶馬的玻璃是否堅硬,不需要啟動我的寶馬加速到120km,然后再用手去翹翹那塊玻璃吧。

           

          所以,我希望能夠有個模擬對象,繼承了這個接口, 同時提供了我期望的返回值,讓這個方法能夠順利執行。

           

          傳統的傻逼方法,就是自己寫一個類,繼承了這個接口,然后才傳入進去。例如:

           

          public class OrmScheduleTriggerTestObject : IOrmScheduleTrigger
          {
          // some method here
          }

           

           

          這樣不就更加的傻逼了?我為了測一塊玻璃,還親自造了另外一臺簡易的寶馬出來? 于是我開始翻閱各種文獻,甚至考慮使用動態代理(DynamicProxy)。動態代理的核心思想就是在代碼運行中寫IL生成一個繼承類。這個技術很有用,但是現在我還用不上(就像martin fowler說的,typemock就等于把核武器交給了一個4歲小孩)。

           

          于是我繼續尋找,終于翻開了Moq的源碼,找到了答案。

           

          先看看以下一段代碼,是我摘自Moq源碼的核心部分,稍加改造了:

           

          復制代碼
          代碼
          using System;
          using System.Collections.Generic;
          using System.Text;
          using System.Runtime.Remoting.Proxies;
          using System.Runtime.Remoting.Messaging;

          namespace Pixysoft.Framework.TestDrivens
          {
              
          public class Mock<TInterface> : RealProxy
              {
                  
          public Mock()
                      : 
          base(typeof(TInterface))
                  {
                  }

                  
          public TInterface Value
                  {
                      
          get
                      {
                          
          return (TInterface)this.GetTransparentProxy();
                      }
                  }

                  
          public override IMessage Invoke(IMessage msg)
                  {
                      IMethodCallMessage methodCall 
          = msg as IMethodCallMessage;

                      
          //我返回int = 1

                      
          return new ReturnMessage(1null0null, methodCall);
                  }
              }

              
          public interface IMock
              {
                  
          int Devide(int a, int b);
              }

              
          public class testrealproxy //測試代碼在這里?。?!
              {
                  
          public void test()
                  {
                      IMock mock 
          = new Mock<IMock>().Value;

                      Console.WriteLine(mock.Devide(
          12));

                      
          //輸出 = 1
                  }
              }
          }
          復制代碼

           

           

          這段代碼就是Moq的核心思想。

           

          大概意思是:我希望調用接口IMock的方法Devide,但是我壓根不想寫這個接口的實現。

           

          那么我先寫一個通用的模擬對象Mock<TInterface>,繼承了RealProxy。

           

          然后通過調用Value就可以返回需要的接口對象。而這個對象就是 return (TInterface)this.GetTransparentProxy();是個透明代理。

           

          最后當我調用了 int Devide(int a, int b); 方法的時候,等于調用了public override IMessage Invoke(IMessage msg)方法(有點點的AOP感覺)。

           

          后記

           

          上文就是Moq的核心思想了。非常的精彩!估計有了思路,各位就可以制造自己的原子彈了。

           

          這里插句題外話,很多人抨擊重復造輪子。我就奇怪了。如果我造一個輪子花費的時間和學習用一個輪子的時間差不遠,為什么不造一個?

          而且,用別人的輪子,經常出現的情況是:很多輪子不知道挑哪個。一旦挑上了,項目進展到一般才發現不適合、有bug,于是又重頭挑另外的輪子。

           

          這個經歷是真實的。當年讀大學,我的室友就是典型的挑輪子,他懂得很多框架(java),webwork,hibernate, spring。和人砍起來朗朗上口,但是需要深入做項目了,出現問題基本上不知所措,不是翻文獻,就是問師兄,最后整個項目組從來就沒有一個成品。

           

          我自從學電腦依賴,從來就沒有用過別人的輪子,即使是hibernate,我的確也沒有用過,不過他的核心文檔倒是看過,對比之下,和oracle的toplink相比簡直就是小孩。

           

          比我牛逼的兄弟大有人在,希望各位牛人不要浪費自己的時間去挑別人的輪子,直接自己造一個算了。 

           

          最后說說接下來的工作。

           

          基于接口的測試驅動完成了,剩下的就是面對sealed class 等頑固分子了, 必然需要動用非常規武器,DynamicProxy。下回再見。

           

           

          分享到:
          posted on 2013-04-20 15:29 abin 閱讀(488) 評論(0)  編輯  收藏 所屬分類: easyMock
          主站蜘蛛池模板: 都匀市| 工布江达县| 运城市| 精河县| 白沙| 清涧县| 卢氏县| 吴堡县| 寻乌县| 教育| 苏州市| 景洪市| 涿鹿县| 鸡西市| 年辖:市辖区| 获嘉县| 安福县| 闽清县| 海林市| 昌黎县| 图们市| 平遥县| 新河县| 乐至县| 济宁市| 五常市| 女性| 桃源县| 盘锦市| 遵化市| 郸城县| 昭苏县| 大悟县| 聂拉木县| 罗源县| 新蔡县| 清涧县| 依兰县| 永新县| 蒲江县| 江川县|