AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

三個要點,掌握Spring Boot單元測試

來源: 責編: 時間:2023-09-28 10:06:01 260觀看
導讀單元測試是軟件開發中不可或缺的重要環節,它用于驗證軟件中最小可測試單元的準確性。結合運用Spring Boot、JUnit、Mockito和分層架構,開發人員可以更便捷地編寫可靠、可測試且高質量的單元測試代碼,確保軟件的正確性和

單元測試是軟件開發中不可或缺的重要環節,它用于驗證軟件中最小可測試單元的準確性。結合運用Spring Boot、JUnit、Mockito和分層架構,開發人員可以更便捷地編寫可靠、可測試且高質量的單元測試代碼,確保軟件的正確性和質量。yfM28資訊網——每日最新資訊28at.com

yfM28資訊網——每日最新資訊28at.com

一、介紹

本文將從與單元測試相關的技術主題開始,在技術部分之后,介紹使用Spring Boot、JUnit和Mockito進行單元測試的實踐。yfM28資訊網——每日最新資訊28at.com

二、測試的關鍵要素

1.單元

單元測試中的單元一詞指的是軟件中可以單獨測試和處理的最小功能部分,通常是指函數、方法、類或模塊等獨立的代碼片段。yfM28資訊網——每日最新資訊28at.com

2.用例

用例描述了系統使用特定功能或特性的方式,用于理解、設計和測試軟件系統的需求。通常包括用戶如何與系統進行交互、對系統的期望以及應該實現的結果等詳細信息。yfM28資訊網——每日最新資訊28at.com

3.邊界情況

邊界情況指的是軟件必須處理的特定場景,這些場景包括意外或邊界條件,與典型情況有所不同或被認為是罕見的情況。邊界情況可以包括意外用戶登錄、測試限制、異常輸入或其他可能導致系統錯誤或異常行為的情況。在測試過程中,考慮和測試邊界情況是非常重要的,因為它們可以幫助開發人員發現潛在的問題并確保系統的魯棒性和穩定性。yfM28資訊網——每日最新資訊28at.com

三、單元測試

單元測試涵蓋了我們可以考慮并編寫的所有可能性。每個單元必須至少有一個測試方法。測試不是為一個方法編寫的,而是為一個單元編寫的。yfM28資訊網——每日最新資訊28at.com

可以按照以下順序編寫單元測試:正常路徑/用例、邊界情況和異常情況。yfM28資訊網——每日最新資訊28at.com

這些步驟是必不可少的,這樣做可以確保單元以正確的方式處理輸入,并生成預期的輸出,展現出預期的行為。單元測試是及早發現風險和修復錯誤的最佳方式。通過單元測試,我們可以預防潛在的意外情況,應對生產代碼的變更,確保生產代碼能夠處理各種情況。簡而言之,單元測試確保了生產代碼的安全性。yfM28資訊網——每日最新資訊28at.com

關于單元測試的另一個重要事項是要測試業務邏輯,不是在單元測試中測試基礎設施代碼,基礎設施代碼可以在集成測試中進行測試。可以考慮使用一些架構模式(如洋蔥架構、六邊形架構等)來將業務邏輯與基礎設施代碼分離。yfM28資訊網——每日最新資訊28at.com

單元測試的另一個優點是速度快,因為它不需要依賴 Spring ApplicationContext。由于上下文的原因,與單元測試相比,同一測試金字塔中的集成測試速度要慢得多。yfM28資訊網——每日最新資訊28at.com

1.開始編碼

在分層架構項目中,業務代碼主要位于服務層。這意味著服務層具有單元,需要進行測試。讓我們聚焦于最關鍵的部分。yfM28資訊網——每日最新資訊28at.com

以下是一段示例代碼:yfM28資訊網——每日最新資訊28at.com

  @Override    public String saveUser(User user) {        validateUser(user);        try {            User savedUser = userRepository.save(user);            return savedUser.getEmail();        } catch (Exception exception) {            throw new IllegalArgumentException(E_GENERAL_SYSTEM);        }    }    private void validateUser(User user) {        if (Objects.isNull(user.getEmail())) {            throw new IllegalArgumentException(E_USER_EMAIL_MUST_NOT_BE_NULL);        }        if (findByEmail(user.getEmail()).isPresent()) {            throw new IllegalArgumentException(E_USER_ALREADY_REGISTERED);        }    }    @Override    public Optional<User> findByEmail(String email) {        return userRepository.findByEmail(email);    }

上述代碼中有兩個公共方法和一個私有方法,私有方法可以被視為公共方法的一部分。此外,由于代碼的復雜性和功能需求,還存在許多可能的場景需要編寫多個測試用例來覆蓋各種情況,以確保代碼的正確性。yfM28資訊網——每日最新資訊28at.com

2.注解

@ExtendWith用于將Mockito庫集成到JUnit測試中。@Test 標記一個方法,使其成為一個測試方法,測試方法包含指定的測試用例,并由 JUnit 自動運行。yfM28資訊網——每日最新資訊28at.com

在測試過程中,需要模擬正在測試的類的依賴項。之前提到的原因是,由于 Spring ApplicationContext 不會啟動,我們無法將依賴項注入到上下文中。@Mock 用于創建一個模擬的依賴項,而 @InjectMocks 則用于將這些模擬的依賴項注入到被測試類中。yfM28資訊網——每日最新資訊28at.com

@BeforeEach和@AfterEach可用于在每個方法運行之前和之后執行相應的操作。yfM28資訊網——每日最新資訊28at.com

@ParameterizedTest 用于使用不同的參數值運行重復的測試用例。通過使用 @ValueSource,可以為方法提供不同的參數值,以便進行多次測試。yfM28資訊網——每日最新資訊28at.com

3.測試方法的三個主要階段

  • Given: 準備測試用例所需的對象
  • When: 執行必要的操作以運行測試場景
  • Then: 檢查或驗證預期結果

doReturn/when 用于確定在給定指定參數時方法的行為方式。但是,由于依賴項是 @Mock,并不會真正執行。yfM28資訊網——每日最新資訊28at.com

verify 用于檢查被測試代碼是否按照預期行為執行。如果要測試的方法是 public void 類型,可以使用 verify 進行驗證。yfM28資訊網——每日最新資訊28at.com

斷言用于驗證預期結果。yfM28資訊網——每日最新資訊28at.com

 @ExtendWith(MockitoExtension.class)class UserServiceImplTest {    @InjectMocks    private UserServiceImpl userService;    @Mock    private UserRepository userRepository;    private User user;    public static final String MOCK_EMAIL = "mert@bahardogan.com";    @BeforeEach    void setUp() {        user = new User();        System.out.println("init");    }    @AfterEach    void teardown() {        System.out.println("teardown");    }    @ParameterizedTest    @ValueSource(strings = {"mert@bahardogan.com", "info@gmail.com"})    @DisplayName("Happy Path: save user use cases")    void givenCorrectUser_whenSaveUser_thenReturnUserEmail(String email) {        // given        user.setUserName("mertbahardogan").setEmail(email).setPassword("pass");        User savedUser = new User().setEmail(email);        doReturn(savedUser).when(userRepository).save(any());        // when        String savedUserEmail = userService.saveUser(user);        // then        verify(userRepository,times(1)).findByEmail(anyString());        verify(userRepository,times(1)).save(any());        assertEquals(email, savedUserEmail);    }    @Test    @DisplayName("Exception Test: user email must not be null case")    void givenNullUserEmail_whenSaveUser_thenThrowsEmailMustNotNullEx() {        // when        Exception exception = assertThrows(IllegalArgumentException.class, () -> userService.saveUser(user));        // then        assertNotNull(exception);        assertEquals(E_USER_EMAIL_MUST_NOT_BE_NULL, exception.getMessage());    }    @Test    @DisplayName("Exception Test: user is already registered case")    void givenRegisteredUser_whenSaveUser_thenThrowsUserAlreadyRegisteredEx() {        // given        user.setEmail(MOCK_EMAIL);        Optional<User> savedUser = Optional.of(new User().setEmail(MOCK_EMAIL));        doReturn(savedUser).when(userRepository).findByEmail(anyString());        // when        Exception exception = assertThrows(IllegalArgumentException.class, () -> userService.saveUser(user));        // then        assertNotNull(exception);        assertEquals(E_USER_ALREADY_REGISTERED, exception.getMessage());    }    @Test    @DisplayName("Exception Test: catch case")    void givenIncorrectDependencies_whenSaveUser_thenThrowsGeneralSystemEx() {        // given        user.setEmail(MOCK_EMAIL);        // when        Exception exception = assertThrows(IllegalArgumentException.class, () -> userService.saveUser(user));        // then        assertNotNull(exception);        assertEquals(E_GENERAL_SYSTEM, exception.getMessage());    }    @Test    @DisplayName("Happy Path: find user by email")    void givenCorrectUser_whenFindByEmail_thenReturnUserEmail() {        // given        Optional<User> savedUser = Optional.of(new User().setEmail(MOCK_EMAIL));        doReturn(savedUser).when(userRepository).findByEmail(anyString());        // when        Optional<User> user = userService.findByEmail(MOCK_EMAIL);        // then        verify(userRepository,times(1)).findByEmail(anyString());        assertEquals(savedUser, user);    }}

UserServiceImpl測試類運行時長為1秒693毫秒。yfM28資訊網——每日最新資訊28at.com

yfM28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-11820-0.html三個要點,掌握Spring Boot單元測試

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: DevOps優秀實踐之用戶與權限

下一篇: C 語言程序是如何在計算機內部工作?

標簽:
  • 熱門焦點
  • 7月安卓手機好評榜:三星S23Ultra好評率第一

    性能榜和性價比榜之后,我們來看最后的安卓手機好評榜,數據來源安兔兔評測,收集時間2023年7月1日至7月31日,僅限國內市場。第一名:三星Galaxy S23 Ultra好評率:95.71%在即將迎來新
  • 服務存儲設計模式:Cache-Aside模式

    Cache-Aside模式一種常用的緩存方式,通常是把數據從主存儲加載到KV緩存中,加速后續的訪問。在存在重復度的場景,Cache-Aside可以提升服務性能,降低底層存儲的壓力,缺點是緩存和底
  • SpringBoot中使用Cache提升接口性能詳解

    環境:springboot2.3.12.RELEASE + JSR107 + Ehcache + JPASpring 框架從 3.1 開始,對 Spring 應用程序提供了透明式添加緩存的支持。和事務支持一樣,抽象緩存允許一致地使用各
  • 如何正確使用:Has和:Nth-Last-Child

    我們可以用CSS檢查,以了解一組元素的數量是否小于或等于一個數字。例如,一個擁有三個或更多子項的grid。你可能會想,為什么需要這樣做呢?在某些情況下,一個組件或一個布局可能會
  • 學習JavaScript的10個理由...

    作者 | Simplilearn編譯 | 王瑞平當你決心學習一門語言的時候,很難選擇到底應該學習哪一門,常用的語言有Python、Java、JavaScript、C/CPP、PHP、Swift、C#、Ruby、Objective-
  • .NET 程序的 GDI 句柄泄露的再反思

    一、背景1. 講故事上個月我寫過一篇 如何洞察 C# 程序的 GDI 句柄泄露 文章,當時用的是 GDIView + WinDbg 把問題搞定,前者用來定位泄露資源,后者用來定位泄露代碼,后面有朋友反
  • Python異步IO編程的進程/線程通信實現

    這篇文章再講3種方式,同時講4中進程間通信的方式一、 Python 中線程間通信的實現方式共享變量共享變量是多個線程可以共同訪問的變量。在Python中,可以使用threading模塊中的L
  • 消息稱小米汽車開始篩選交付中心:需至少120個車位

    IT之家 7 月 7 日消息,日前,有微博簡介為“汽車行業從業者、長三角一體化擁護者”的微博用戶 @長三角行健者 發文表示,據經銷商集團反饋,小米汽車目前
  • 華為Mate 60系列用上可變靈動島:正式版體驗將會更出色

    這段時間以來,關于華為新旗艦的爆料日漸密集。據此前多方爆料,今年華為將開始恢復一年雙旗艦戰略,除上半年推出的P60系列外,往年下半年的Mate系列也將
Top