最近爲了給Jumony for ASP.NET進行單元測試有點傷神,ASP.NET由於環境特殊,一直是單元測試的禁地,傳統的單元測試工具因爲運行在非ASP.NET環境,可謂是舉步維艱。固然,微軟在搞ASP.NET MVC的時候已經注意到了這一點,僱了不少個臨時工把HttpContext以及全部的相關類型所有寫了個Base和Wrapper類型,用來Mock一個HttpContext僞裝在ASP.NET環境。有了這些對象,測試個MVC的Controller和Action也夠用了(只是我還沒找到自動Mock這一大坨對象的方法)。可是ASP.NET環境顯然不止這些,譬如說你們不多用到的VirutalPathUtility就在其列。因爲Jumony for ASP.NET是個框架性質的項目,因此一些框架底層不經常使用的東西隨處可見。固然,也有人不堪其擾,對這個東西也改造了一番: git
還有這個: github
但這些都是internal的,我不能直接用之,再說,指不定哪天就成了public的,個人還與其衝突。最後,我也沒有微軟那麼多臨時工去一個個方法Mock出來。想來想去,個人要求再簡單不過,只要有個HttpRuntime就行了,不妨直接用真的ASP.NET環境。 app
用真的ASP.NET環境有幾個方案,VS自帶的測試工具支持ASP.NET的測試,可是摸索了半天,發現侷限大的很,還只能測試aspx文件,用起來也很是的不方便,徹底不能知足個人要求,遂放棄。 框架
而後又想,乾脆本身用控制檯搭一個ASP.NET運行環境出來,這樣的話就能夠本身發個請求進去,讓裏面的代碼執行個結果扔出來。雖然說微軟提供了本身搭建ASP.NET環境的類型和工具,可是因爲宿主和ASP.NET環境是在兩個AppDomain,通訊不便不說,調試起來也特別麻煩,網站編譯什麼都是事兒。 工具
最後,終於想到,TMD乾脆本身在ASP.NET環境搭一個單元測試框架算了。話說其實一個單元測試框架就是找到測試方法而後所有跑一次,再看看有沒有什麼AsertException之類的東西,顯示出來就完了。我直接在ASP.NET環境搭一個,整個單元測試都在網站跑,就什麼問題都解決了。 單元測試
而後,就有了WebTest這個開源項目: 測試
https://github.com/Ivony/WebTest 網站
既然是從新搞,那新的技術神馬的全都給用上,之前的Assert是個靜態類,一大堆的靜態方法,有些斷言沒有就只好轉換成真假再去判斷。新的框架索性把Assert弄成個對象,全部的斷言方法都給整成擴展方法,大家愛有多少斷言就有多少,不夠再來補充包。之前的測試得本身寫個靜態類,而後每一個方法都要加個[TestMethod]告訴框架這個方法是個測試用的,而我以爲這純屬多餘。只須要寫一個類型,裏面全部的無參public方法所有都被認爲是測試方法,反正框架都會一個個來跑。 設計
肯定好思路後,作起來仍是很快的。首先我想到要有一個類型負責運行測試。 調試
而後來設計這個類型:
設計後的結果就是以下圖:
再加上一個找到全部測試類的靜態方法,TestManager就差很少了。
而後是設計TestResult類型,呈現結果的時候,最關鍵的只有兩個元素,消息和是否成功,而後針對三種測試結果,設計三個派生類:
再而後定義一個測試基類,繼承於這個類型的全部類型都是測試類:
Initialize和Cleanup如今均可以定義爲這個基類的虛方法,若是須要的話就重寫好了,事實上查找測試類型的時候,查找基類比查找Attribute要快,我想不通如今的測試框架爲啥都要弄個特性來標識。
測試基類提供了一個Assert對象,這個對象能夠用來進行斷言:
由於全部的斷言方法都作成擴展方法,因此斷言失敗的時候須要調用Failure方法來描述斷言失敗了。
至此,OOD就基本完成了,而後是一些細節的實現。
查找全部測試類型:
找全部測試方法:
建立Invoker:
事實上,若是熟悉ASP.NET MVC的代碼,這些看似高深的東西並不費神。
最後,寫一個IHttpHandler做爲總控,運行測試,並顯示測試結果,而後,就能夠直接寫單元測試用例了。
固然,做爲一個單元測試框架,目前還有諸多欠缺的地方,例如僞造指定URL的請求,分析代碼覆蓋率等,若是我有時間的話,會繼續完善這個框架的。
事實上,單元測試並不難,即便是搭建一個測試框架,也就是幾百行代碼的事情,咱們有什麼理由不去作呢?