測試篇——初探單元測試

初探單元測試

目錄:

  • 單元測試的核心意義

  • 單元測試的特色

  • 一個簡單的單元測試demo

  • 構建可測試的代碼以及初探Mock框架NSubstitute

 

單元測試的核心意義

  • 驗證代碼健壯性,無 Bug
  • 項目升級,重構後涉及到舊的邏輯,保證以舊邏輯的穩定運行

單元測試的特色

  • 單元測試可重複運行
  • 單元測試持續長期有效,而且返回結果一致
  • 單元測試在內存中運行,不會依賴外部組建(例如真實的數據庫,真實的文件等)
  • 單元測試能夠快速返回結果
  • 一個測試方法只測試一個問題(最小的粒度)

一個簡單的單元測試demo

  • 這裏建立一個類 Product 表明商品; ProductCollection 表明配送的商品集合, DistributeProduct 方法根據傳入的商品 Id 集合表明須要配送的商品(具體看項
    目代碼)數據庫

  • 建立一個基於 Framework 的單元測試項目 MyUnitTestApplication ,添加一個單元測試類 ProductCollectionTests , ,添加一個單元測試方
    法 ProductCollction_DistributeProduct_Test 編程

    • 注意點 1 :單元測試方法命名規範通常是 測試主體 _ 期待返回結果 _ 傳入參數。
    • 注意點 2 :單元測試類須要添加 [TestClass] 特性,單元測試方法須要 [TestMethod] 特性修飾
    • 在單元測試的方法體內右鍵運行單元測試,以下圖所示,能夠在右側測試資源管理器中看到看到運行結果;例如把第三個斷言修改爲一個錯誤的結果,右
      鍵運行單元測試,就會出現測試未經過顯示。框架

    • 這樣一個最簡單的單元測試就寫完了,假如未來有人修改了 DistributeProduct 方法,再將這個單元測試運行一遍就能夠驗證修改是否存在 Bug.單元測試

構建可測試性的代碼

  • 關於 demo 的依賴性問題:單元測試的用例可以成功運行取決於內部全部邏輯正常運行,例如上面 demo 中的測試核心是 DistributeNotice 對象,由於測試

的是它的 ToNotice 方法向外部發送通知消息。因此這裏的 ProductCollection 對象依賴於 DistributeNotice 對象。可是,通常向外部發送信息須要 一些配置以測試

及 第三方的代理類(外部依賴)。例如以下圖所示: DirstributeNotice 對象依賴着 ConfigurationManager 和 EmailSend 。此時單元測試已經不能進行了,由於需
要考慮其餘的外在因素。
spa

  •   

     

  • 咱們的解決方案是:此時咱們能夠添加一個 間接層。讓本來依賴於 類或者 外部資源的對象抽象成依賴於它們的 接口,而後經過接口動態生成一個模擬的實現
    類。(這也是設計原則中所謂的 面向接口編程)因而咱們的依賴關係變爲下圖:設計

 

  • 修改咱們的代碼,將實現類抽象成爲接口;

基於接口重寫編寫單元測試,這裏咱們用到了 Mock 接口單元測試,使用了開源的 Mock 框架 NSubstitute 。(測試過程當中替代真實對象的內存級別虛
擬對象)3d

  • 因此,單元測試的關鍵是面向接口,面向抽象。使各個組件,各個類依賴於接口,當代碼耦合度太高將沒法進行單元測試。
  • 當咱們須要測試一些類中受保護的方法測試時候,將會遇到下面的問題:
    •  在咱們實現業務過程當中,在類的內部常常會出現一些受保護的方法,而後測試類只會有一個公共的入口,此時咱們要怎樣測試這些受保護的方

      法的業務邏輯呢?例以下圖所示:咱們在咱們的 ProductCollection 集合類中添加一個方法 ValidatorProduct , ,根據產品的編號,判斷產品的數量和價格是否合適,從而代理

      判斷這個產品是否合適。在編寫方法過程當中,咱們遵循單一職責原則,將驗證邏輯碎片化以備未來擴展和重用,可是這些邏輯都是重要邏輯,咱們想
      要測試它們,然而咱們只有一個公共的方法入口 ValidatorProduct ,咱們不能單獨的測試其中一個的邏輯。
      對象

此時咱們的解決方案是:咱們能夠在測試環境下,提供一個繼承於測試類的子類,在子類中提供這些方法的可測試版本。以下圖所示:咱們創建了一個子

類 ProductCollectionAccessibility , ,經過繼承的方式,在 ValidatorPriceAccessibility 方法中和 ValidatorNumberAccessibility 分別測試父類的驗證產品價格和數
量的方法。

咱們常常須要完善咱們的測試用例,

  • 咱們的代碼完成後會持續的進行修改,重構。在這個過程當中,代碼會進行修改,從而會對之前的代碼形成影響。此時咱們就須要一個保障。這個保證就是

單元測試,基於一個測試用例很完善的單元測試項目,咱們修改後,只須要將單元測試從新運行一遍,就能夠保證重構修改代碼是否有 Bug ,是否有副做
用。

  • 單元測試不單單驗證代碼正確性,無 Bug, 也保證了代碼在生命週期中一直被完善和重構,讓其愈來愈有價值,不會成爲公司的技術債務。
相關文章
相關標籤/搜索