日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

测试用例-单元测试

發布時間:2024/8/1 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 测试用例-单元测试 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

單元測試——編寫手冊

1.簡述

本文主要針對如何使用Junit編寫單元測試進行描述
文中的實例基于Junit 4

所謂單元測試,即是指針對程序中的一些單元進行測試的方法 這些單元在Junit中的最小單位為方法 借助單元測試,我們可以輕松地單獨測試程序中的某一個邏輯片段而不需要在意程序的外部依賴和其它邏輯 接口測試單元測試
只能以接口為維度進行測試只需被測試的單元邏輯正常即可
工程必須編譯通過并打包進行部署可以不依賴外部,測試進度不再受制于外部條件
工程的外部依賴(數據庫、調用的服務等)必須就緒可以以方法為維度進行測試
難以測試復雜的邏輯分支,為測試數據需要調整各個數據源(數據庫、緩存、消息隊列)可以根據單元的邏輯復雜程度編排測試用例數量,測試使用的數據可以自由調整

2.創建測試用例

2.1工程準備

  • 確保工程的maven依賴中包含junit,版本至少為4.12,一般包含在spring-boot-starter-test中;

  • 確保工程的目錄中包含src/test/java和src/test/resource;

    *部分工程沒有src/test的相關包,需要手動創建
    *src/test/java主要用于存放測試用例和測試相關的類
    *src/test/resoutces主要用于存放測試使用的配置和資源文件

  • 2.2 編寫測試啟動類

    許多工程在啟動時需要加載許多配置類,與外部系統進行連接,非常復雜 為了使單元測試更加輕便,我們可以編寫單元測試專用的啟動類,屏蔽一些不相關的啟動項 若你的工程啟動和外部連接依賴本身就很簡單,可以省略這一步,不寫測試啟動類則執行測試時默認使用 src/main/java下的啟動類 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.FilterType;@ComponentScan(basePackages = { "需要掃描的包名" }, excludeFilters = {@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = { 掃描的包中需要排除的類 }) }) @SpringBootApplication(exclude = { 需要排除的一些啟動時自動配置類 }) public class TestApplication {public static void main(String[] args) {SpringApplication.run(TestApplication.class, args);} }

    這個啟動類中常用的配置如下

  • @ComponentScan
    用于掃描指定的包,excludeFilters用于排除掃描的包中不需要的Bean
  • @SpringBootApplication
    用于排除一起自動配置的啟動類,防止諸如數據庫、Mongo等啟動類進行外部連接
    測試的啟動類與工程的啟動類類似,它通常防止在src/test/java下的項目根包中
  • 其中“需要掃描的包名”和“掃描的包中需要排除的類”根據具體的工程決定,可按需將工程中的一些啟動時配置類排除在外(Cache配置等),保證你測試的類以及它們的直接依賴被掃描到即可
    “需要排除的一些啟動時自動配置類”可參考如下對照表按需排除

    作用全類名
    MongoDB自動配置org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
    org.springframework.boot.autoconfigure.data.mongo.MongoRepositoriesAutoConfiguration
    數據源自動配置org.springframework.boot.autoconfigure.data.mongo.MongoDataAutoConfiguration
    Hibernate注解自動配置org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

    啟動類的掃描配置決定了測試用例的范圍以及啟動速度
    可以按需編寫多個不同掃描范圍的啟動類以適配不同的測試需求

    2.3 構建抽象測試類

    根據啟動類創建一個抽象測試類是個好方法,它能夠讓你在創建測試用例時通過選擇繼承的父類直接確定使用的測試啟動配置。

    import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.test.context.junit4.SpringRunner;@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.NONE, classes = 啟動類) public abstract class BaseTest {}

    @SpringBootTest
    用于指定測試的一些主要參數,主要是classes,用于指定關聯的啟動類,這樣繼承自這個類的所有子類都會使用相同的啟動類

    2.4 使用測試專用的配置

    就像在工程部署時我們可以指定不同環境的配置文件一樣;
    執行測試時我們也可以使用不同的配置文件;
    使用自定義測試啟動類的情況下將配置文件放置在src/test/resource下則測試類默認會使用該包下的配置和資源文件;
    由于測試啟動類中通常會排除許多與測試目標無關的類,所以測試專用的配置文件可以更加輕量化,哪些被排除的類所引用的配置都可以省略;

    2.5 新建Test類

    針對一個被測類創建一個測試類 測試類通常以被測類的名字+Test進行命名,并放置在與src/test/java下與被測類同包名的包中
  • 根據被測類創建測試類
  • 配置測試類的參數,通常這些參數會按照約定給出一些默認值;
  • 選擇要測試的方法,注意:junit測試只能對非private方法進行測試DemoServiceTest,測試用例在src/test/java下的被測類同名包中;此時可以選擇繼承的父類,根據測試需要進行繼承
  • 生成測試類,得到一個單元測試類的骨架,包含了選擇的方法的測試用例
  • 編寫用例

    3.1 了解Mock測試


    一個Bean通常會形成一個依賴樹,這種發散的依賴結構導致我們在測試一個類的邏輯時其實是連同它所依賴的邏輯一同進行測試

    此時使用Mock測試就可以解決依賴過多,邏輯復雜的問題

    Mock以為模擬、虛擬,就是將原有的邏輯進行模擬,使用規劃的Mock方案邏輯進行替代

    在Mock測試中,我們通常對測試對象的所有直接依賴進行Mock,被Mock的直接依賴將變成只有方法簽名的空殼

    被調用時它們不會再調用間接依賴,也不會執行原有的邏輯,只會根據Mock方案進行返回

    這樣在測試測試對象時我們就不在需要關心它負載的間接依賴關系和所有依賴的內部邏輯了,只需要專注于當前測試對象的邏輯即可

    3.2 完全Mock依賴

    這種測試僅測試測試對象內部的邏輯,屏蔽所有測試對象的依賴
    適用于測試內部邏輯較為復雜的對象,或依賴較為復雜的對象
    樣例:

    注意

  • @MockBean標記的依賴的方法默認變為空方法且返回值為null,一定要配合mock方案才能執行邏輯和獲取返回值(參照FAQ-@MockBean與@SpyBean)
  • mock方案的編寫參照FAQ-mock方案
  • 需要調用@MockBean標記的類中無返回值的方法時可以不編寫mock方案,但一定要校驗調用是否執行(參照FAQ-驗證調用是否執行)
  • 3.3 完全真實依賴

    這種類型的測試同時測試測試對象及全部其依賴的邏輯,針對實際調用流程進行測試 適用于測試一個完整的流程以及測試調用鏈路正確性

    樣例

    注意

  • 這種測試方式與Mock毫無關系,為常規的方法邏輯調用
  • 測試的結果與輸入的數據、持久化的數據、程序邏輯直接相關,因此需要事先準備好配套得入參、數據庫腳本/Redis緩存并熟悉程序的邏輯,以此推導出正確的處理結果
  • 3.4 Mock與真實依賴相結合

    這種類型的測試同時測試測試對象及其部分依賴的邏輯,屏蔽部分較為復雜的依賴同時對實際調用流程進行測試 適用于測試一個部分依賴較為復雜的流程以及測試調用鏈路正確性

    樣例:

    注意

  • @SpyBean標記的依賴的方法默認為真實邏輯,若配合mock方案則在入參與mock方案一致時根據mock方案的設置進行返回(參照FAQ-@MockBean與@SpyBean)
  • mock方案的編寫參照FAQ-mock方案
  • 需要調用@SpyBean標記的類的方法的真實邏輯時可以不編寫mock方案
  • 測試的結果與輸入的數據、持久化的數據、程序邏輯、mock方案均相關,因此需要事先準備好配套得入參、數據庫腳本/Redis緩存并熟悉程序的邏輯和mock方案的邏輯,以此推導出正確的處理結果
  • 雖然@SpyBean標記的類在沒有設置mock方案的情況下原則上與原類的邏輯一致,但由于底層實現原理的種種限制,它與原生的類在某些情況下不能完全一致;若想直接測試完全真實依賴的場景,請參照完全使用真實依賴的測試章節的描述
  • 3.5 混合測試

    對一個測試對象中的不同方法采取不同的測試策略 對同一個測試對象的不同方法根據需求采取“完全Mock”或“完全真實”或“Mock與真實結合”的方式;沒有對同一個測試 對象編寫多個不同類型測試用例的需求

    注意

  • 此種測試是其他3種的復合形式,單個用例內的書寫參照相應章節的描述
  • 此種測試的測試對象的依賴需要使用@SpyBean的方式進行標記,否則難以執行真實邏輯(參照FAQ-@MockBean與@SpyBean)
  • 4. FAQ

    4.1 @MockBean與@SpyBean

    在進行mock測試或混合測試時可以看到這2中不同的設定測試對象直接依賴的注解 /相同不同
    @MockBean提供mock測試能力mock方案的作用域都在一個@Test內默認將標記該注解的類及其依賴的方法全部掏空,直接調用將沒有任何執行邏輯并返回null(如果有返回值)
    @SpyBean提供mock測試能力mock方案的作用域都在一個@Test內默認將標記該注解的類以及依賴的方法保持原樣,直接調用將按照方法原本的邏輯執行并返回;可以按照混合測試的需求靈活決定是否mock
    /使用場景
    @MockBean適用于標記的依賴需要被完全mock的場景,不配合mock方案使用易引發空指針異常
    @SpyBean適用于標記的依賴只有部分邏輯需要mock的場景,不配合mock方案則執行原方法,配合mock方案則執行mock方案

    4.2 mock方案

    在進行mock測試時需要提前針對被mock的邏輯進行規劃
    參照如下寫法:

    Mockito.doReturn(mockData).when(demoService).function(Matchers.eq(arg1), Matchers.eq(arg2)); Mockito.doNothing().when(demoService).function(Matchers.eq(arg1), Matchers.eq(arg2)); Mockito.doThrow(exception).when(demoService).function((Matchers.eq(arg1), Matchers.eq(arg2)); 關鍵詞解釋
    doReturn(mockData)模擬方法正常返回數據
    doNothing()模擬方法未執行(可用于沒有返回值的方法)
    doThrow(exception)模擬方法執行時拋出異常
    demoService被@MockBean或@SpyBean標記的測試對象的直接依賴
    function、arg1、arg2直接依賴的方法名及其參數
    Matchers.eq()org.mockito.Matchers提供的一些更靈活的mock調用時參數驗證方法;驗證通過時方法返回模擬的返回數據,驗證不通過時方法按照@MockBean或@SpyBean的默認策略執行

    4.3 同名方法調用多次

    同名方法設置多個mock方案時,不同入參預期的方案都會保留,相同入參預期的方案以最后一個為準
    例,設置了如下mock方案:

    @MockBean private DemoService demoService;@Test public void testFunction() {// 省略其他步驟,此處只展示mock方案設置// 方案1Mockito.doReturn(demoDataA).when(demoService).callFun(eq("alpha"));// 方案2Mockito.doReturn(demoDataB).when(demoService).callFun(eq("beta"));// 方案3Mockito.doCallRealMethod().when(demoService).callFun(eq("beta")); }

    方案1,3會生效,方案2會被方案3覆蓋而失效
    調用demoService.callFun(String)方法時:
    若入參為"alpha",則返回demoDataA;
    若入參為"beta",則執行該方法的真實邏輯并返回;
    若入參為其他,則執行空方法并返回null(@MockBean的默認方案);
    在上述場景的基礎上,若被測方法中存在同一方法調用多次且入參相同,但根據執行順序返回值不同,則參照如下寫法(使用鏈式調用依序排布多個方案):

    @MockBean private DemoService demoService;@Test public void testFunction() {// 省略其他步驟,此處只展示mock方案設置// 方案1Mockito.doReturn(demoDataA).when(demoService).callFun(eq("alpha"));// 方案2(包含多次調用的方案)Mockito.doReturn(demoDataB).doCallRealMethod().when(demoService).callFun(eq("beta")); }

    調用demoService.callFun(String)方法時:

    若入參為"alpha",則返回demoDataA;
    若入參為"beta"且是該入參的第1次調用,則返回demoDataB;
    若入參為"beta"且是該入參的第2次調用,執行該方法的真實邏輯并返回;
    若入參為"beta"且是該入參的第3次及以上調用,執行方案鏈中最后一個方案(例子中為調用真實邏輯);
    若入參為其他,則執行空方法并返回null(@MockBean的默認方案)

    4.4 驗證調用是否執行

    在mock測試中需要驗證mock方案標記的方法是否按照預期的入參執行過,若缺少這一步可能導致測試用例出現未預期的成功
    例,一個用例按如下步驟執行:

  • 測試的依賴使用@SpyBean標注
  • 執行到mock方案對應的方法,入參與mock方案預期不一致
  • 方法按照真實邏輯執行
  • 方法的返回值恰巧與預期一致
  • 測試成功
  • 上述例子的用例可能會在某次數據庫數據變動,外部鏈接中斷的場景下執行失敗
    增加驗證調用是否執行的步驟可以解決該問題
    寫法如下:

    Mockito.verify(demoService).function(Matchers.eq(arg1), Matchers.eq(arg2));

    與mock方案中的寫法非常相似
    當同名方法調用多次且入參一致時采用如下寫法:

    Mockito.verify(demoService, new Times(2)).function(Matchers.eq(arg1), Matchers.eq(arg2));

    總結

    以上是生活随笔為你收集整理的测试用例-单元测试的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。