我們在使用 spring 開發專案時,都會用到依賴注入。如果程式依賴了外部系統或者不可控元件,比如依賴資料庫、網路通訊、檔案系統等,我們在編寫單元測試時,並不需要實際對外部系統進行操作,這時就要將被測試**與外部系統進行解耦,而這種解耦方法就叫作 「mock」。所謂 「mock」 就是用乙個「假」的服務代替真正的服務。
那我們如何來 mock 服務進行單元測試呢?mock 的方式主要有兩種:手動 mock 和利用單元測試框架 mock。其中,利用框架 mock 主要是為了簡化**編寫。我們這裡主要是介紹利用框架 mock,而手動 mock 只是簡單介紹。
手動 mock 其實就是重新建立乙個類繼承被 mock 的服務類,並重寫裡面的方法。在單元測試中,利用依賴注入的程式設計客棧方式使用 mock 的服務類替換原來的服務類。具體**示列如下:
/*** userrepository
* * @author star
*/@repository
public class userrepository
}/**
* mockuserrepository
* * @author star
*/public class mockuserrepository extends userrepository
}// 進行單元測試
@runwith(springrunner.class)
@springboottest
public class userservicemanualtest
}從上面的**中,我們可以看到手動 mock 需要編寫大量的額外**,同時被測試類也需要提供依賴注入的入口(setter 方法等)。如果被 mock 的類修改了函式名稱或者功能,mock 類也要跟著修改,增加了維護成本。
為了提高效率,減少維護成本,我們推薦使用單元測是框架進行 mock。
這裡我們主要介紹 mokito.mock()、@mock、@mockbean 這三種方式的 mock。
mocito.mock()
mocito.mock() 方法允許mufzkkwsp我們建立類或介面的 mock 物件。然後,我們可以使用 mock 物件指定其方法的返回值,並驗證其方法是否被呼叫。**示列如下:
@test
public void testgetuser_mockmethod()
@mock
@mock 是 mockito.mock() 方法的簡寫。同樣,我們應該只在測試類中使用它。與 mockito.mock() 方法不同的是,我們需要在測試期間啟用 mockito 註解才能使用 @mock 註解。
我們可以呼叫 mockitoannotations.initmocks(this) 靜態方法來啟用 mockito 註解。為了避免測試之間的***,建議在每次測試執行之前先進行以下操作:
@before
public void setup()
我們還可以使用另一種方法來啟用 mockito 註解。通過在 @runwith() 指定 mockitojunitrunner 來執行測試:
@runwith(mockitojunitrunner.class)
public class userservicemocktest
下面我們來看看如何使用 @mock 進行服務 mock。**示列如下:
@runwith(springrunner.class)
@springboottest
public class userservicemocktest
@before
public void setup()
@test
public void testgetuser_mockannotation()mufzkkwsp
}mockito 的 @injectmocks 註解作用是將 @mock 所修飾的 mock 物件注入到指定類中替換原有的mufzkkwsp物件。
@mockbean
@mockbean 是 spring boot 中的註解。我們可以使用 @mockbean 將 mock 物件新增到 spring 應用程式上下文中。該 mock 物件將替換應用程式上下文中任何現有的相同型別的 bean。如果應用程式上下文中沒有相同型別的 bean,它將使用 mock 的物件作為 bean 新增到上下文中。
@mockbean 在需要 mock 特定 bean(例如外部服務)的整合測試中很有用。
要使用 @mockbean 註解,我們必須在 @runwith() 中指定 springrunner 來執行測試。**示列如下:
@runwith(springrunner.class)
@springboottest
public class userservicemockbeantest
@test
public void testgetuser_mockbean()
}這裡需要注意的是,spring test 缺省會重用 bean。如果 a 測試使用 mock 物件進行測試,而 b 測試使用原有的相同型別物件進行測試,b 測試在 a 測試之後執行,那麼 b 測試拿到的物件是 mock 的物件。一般這種情況是不期望的,所以需要用 @dirtiescontext 修飾上面的測試避免這個問題。
最後,小夥伴們可以在 github 中獲取原始碼。
如何進行單元測試
一 單元測試步驟 編寫完成後的單元測試工作主要分為兩個步驟 人工靜態檢查 人工靜態檢查是測試的第一步,這個階段工作主要是保證 演算法的邏輯正確性 盡量通過人工檢查發現 的邏輯錯誤 清晰性 規範性 一致性 演算法高效性。並盡可能的發現程式中沒有發現的錯誤。動態執行跟蹤 執行待測程式來跟蹤比較實際結果與...
如何進行Django單元測試?
django的單元測試使用python的unittest模組,這個模組使用基於類的方法來定義測試。類名為django.test.testcase,繼承於python的unittest.testcase。from django.test import testcase class animaltest...
我討厭單元測試 滕振宇談如何進行單元測試
說起單元測試的好處相信大家都能列舉出不少,可是很多時候,開發人員面對自己產品的 想寫單元測試卻無從下手,久而久之,便會有人大喊 我討厭單元測試。資深敏捷諮詢師騰振宇 daniel teng 在gtug topgeek開發工程管理沙龍就以此為題,結合最近的乙個專案,和大家分享了他對單元測試的一些看法。...