欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用SpringBoot編寫一個優(yōu)雅的單元測試

 更新時間:2023年07月21日 17:03:20   作者:Young丶  
這篇文章主要為大家詳細介紹了如何使用SpringBoot編寫一個優(yōu)雅的單元測試,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起了解一下

什么是單元測試

當(dāng)一個測試滿足下面任意一點時,測試就不是單元測試 (by Michael Feathers in 2005):

  • 與數(shù)據(jù)庫交流
  • 與網(wǎng)絡(luò)交流
  • 與文件系統(tǒng)交流
  • 不能與其他單元測試在同一時間運行
  • 不得不為運行它而作一些特別的事

如果一個測試做了上面的任何一條,那么它就是一個集成測試。

不要用 Spring 編寫單元測試

@SpringBootTest
class OrderServiceTests {
    @Autowired
    private OrderRepository orderRepository;
    @Autowired
    private OrderService orderService;
    @Test
    void payOrder() {
        Order order = new Order(1L, false);
        orderRepository.save(order);
        Payment payment = orderService.pay(1L, "4532756279624064");
        assertThat(payment.getOrder().isPaid()).isTrue();
        assertThat(payment.getCreditCardNumber()).isEqualTo("4532756279624064");
    }
}

這是一個單元測試嗎?首先@SpringBootTest注解加載了整個應(yīng)用上下文,而僅僅是為了注入兩個 Bean。

另一個問題是我們需要讀取和寫入訂單到數(shù)據(jù)庫,這也是集成測試的范疇。

Spring Framework 文檔對于單元測試的描述

真正的單元測試運行的非???,因為不需要運行時去裝配基礎(chǔ)設(shè)施。強調(diào)將真正的單元測試作為開發(fā)方法的一部分可以提高你的生產(chǎn)力。

編寫 “可單元測試” 的 Service

Spring Framework 文檔對于單元測試的另一描述

依賴注入可以讓你的代碼減少依賴。POJO 可以讓你的應(yīng)用可以通過new操作符在 JUnit 或 TestNG 上進行測試,不需要任何的 Spring 和其他容器

考慮如果編寫這樣的 Service,它方便進行單元測試嗎???

@Service
public class BookService {
    @Autowired
    private BookRepository repository;
    // ... service methods
}

不方便,因為BookRepository通過@Autowired被注入到 Service 中,并且repository是一個私有變量,這就限定了外界只能通過 Spring 或其它依賴注入容器(或反射)設(shè)置這個值,那么單元測試如果不想加載整個 Spring 容器,那么它就無法使用這個 Service。

而如果這樣寫,使用構(gòu)造方法注入,外界也可以通過new去自行傳遞Repository,這樣即使沒有 Spring,外界也能進行快速的測試。這可能也是 Spring 不推薦屬性注入的原因。

@Service
public class BookService {
    private BookRepository repository;
    @Autowired
    public BookService(BookRepository repository) {
        this.repository = repository;
    }
}

編寫單元測試

Mockito 介紹

前面的知識表明,單元測試就是對一個系統(tǒng)中的某個最小單元的邏輯正確性的測試,通常是對一個方法來進行測試,因為只測試邏輯正確性,所以這個測試是獨立的,不與任何外界環(huán)境相關(guān),比如不需要連接數(shù)據(jù)庫,不訪問網(wǎng)絡(luò)和文件系統(tǒng),不依賴其他單元測試。但是現(xiàn)實的業(yè)務(wù)邏輯中往往有很多復(fù)雜錯綜的依賴關(guān)系,比如你想對 Service 進行單元測試,那么它要依賴一個數(shù)據(jù)庫持久層的 Repository 對象,這時候就難辦了,若創(chuàng)建了一個 Repository 便連接了數(shù)據(jù)庫,連接了數(shù)據(jù)庫便不是一個獨立的單元測試。

Mockito 是一個用來在單元測試中快速模擬那些需要與外界環(huán)境溝通的對象,以便我們快速的、方便的進行單元測試而不用啟動整個系統(tǒng)。

下面的代碼就是 Mockito 的一個基礎(chǔ)使用,Mock 意為偽造。

// 通過mock方法偽造一個orderRepository的實現(xiàn),這個實現(xiàn)目前什么都不會做
orderRepository = mock(OrderRepository.class);
// 通過mock方法偽造一個paymentRepository的實現(xiàn),這個實現(xiàn)目前什么都不會做
paymentRepository = mock(PaymentRepository.class)
// 創(chuàng)建一個Order對象以便一會兒使用
Order order = new Order(1L, false);
// 使用when方法,定義當(dāng)orderRepository.findById(1L)被調(diào)用時的行為,直接返回剛剛創(chuàng)建的order對象
when(orderRepository.findById(1L)).thenReturn(Optional.of(order));
// 使用when方法,定義當(dāng)paymentRepository.save(任何參數(shù))被調(diào)用時的行為,直接返回傳入的參數(shù)。
when(paymentRepository.save(any())).then(returnsFirstArg());

單元測試

class OrderServiceTests {
    private OrderRepository orderRepository;
    private PaymentRepository paymentRepository;
    private OrderService orderService;
    @BeforeEach
    void setupService() {
        orderRepository = mock(OrderRepository.class);
        paymentRepository = mock(PaymentRepository.class);
        orderService = new OrderService(orderRepository, paymentRepository);
    }
    @Test
    void payOrder() {
        Order order = new Order(1L, false);
        when(orderRepository.findById(1L)).thenReturn(Optional.of(order));
        when(paymentRepository.save(any())).then(returnsFirstArg());
        Payment payment = orderService.pay(1L, "4532756279624064");
        assertThat(payment.getOrder().isPaid()).isTrue();
        assertThat(payment.getCreditCardNumber()).isEqualTo("4532756279624064");
    }
}

現(xiàn)在我們即使不想連接數(shù)據(jù)庫,也可以通過mock來給定一個 Repository 的其他實現(xiàn),這樣這個方法可以在毫秒內(nèi)完成。

也可以使用Mockito

@ExtendWith(MockitoExtension.class)
class OrderServiceTests {
    @Mock
    private OrderRepository orderRepository;
    @Mock
    private PaymentRepository paymentRepository;
    @InjectMocks
    private OrderService orderService;
    // ...
}

以上就是使用SpringBoot編寫一個優(yōu)雅的單元測試的詳細內(nèi)容,更多關(guān)于SpringBoot單元測試的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Java利用Netty時間輪實現(xiàn)延時任務(wù)

    Java利用Netty時間輪實現(xiàn)延時任務(wù)

    時間輪是一種可以執(zhí)行定時任務(wù)的數(shù)據(jù)結(jié)構(gòu)和算法。本文將為大家詳細講解一下Java如何利用Netty時間輪算法實現(xiàn)延時任務(wù),感興趣的小伙伴可以了解一下
    2022-08-08
  • win10下定時運行與開機自啟動jar包的方法記錄

    win10下定時運行與開機自啟動jar包的方法記錄

    這篇文章主要給大家介紹了關(guān)于win10下定時運行與開機自啟動jar包的相關(guān)資料,文中通過圖文介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • Java無界阻塞隊列DelayQueue詳細解析

    Java無界阻塞隊列DelayQueue詳細解析

    這篇文章主要介紹了Java無界阻塞隊列DelayQueue詳細解析,DelayQueue是一個支持時延獲取元素的無界阻塞隊列,隊列使用PriorityQueue來實現(xiàn),隊列中的元素必須實現(xiàn)Delayed接口,在創(chuàng)建元素時可以指定多久才能從隊列中獲取當(dāng)前元素,需要的朋友可以參考下
    2023-12-12
  • Java8新特性之新日期時間庫的使用教程

    Java8新特性之新日期時間庫的使用教程

    這篇文章主要給大家介紹了關(guān)于Java8新特性之新日期時間庫使用的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Java輕松實現(xiàn)在Excel中添加超鏈接功能

    Java輕松實現(xiàn)在Excel中添加超鏈接功能

    這篇文章主要為大家詳細介紹了Java如何輕松實現(xiàn)在Excel中添加超鏈接功能,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-01-01
  • SpringBoot整合OpenCV的實現(xiàn)示例

    SpringBoot整合OpenCV的實現(xiàn)示例

    這篇文章主要介紹了SpringBoot整合OpenCV的實現(xiàn)示例。文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • Spring框架 XML配置事務(wù)控制的步驟操作

    Spring框架 XML配置事務(wù)控制的步驟操作

    這篇文章主要介紹了Spring框架 XML配置事務(wù)控制的步驟操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-09-09
  • Java的封裝類和裝箱拆箱詳解

    Java的封裝類和裝箱拆箱詳解

    Java中存在基礎(chǔ)數(shù)據(jù)類型,但是在某些情況下,我們要對基礎(chǔ)數(shù)據(jù)類型進行對象的操作,例如,集合中只能存對象,而不能存在基礎(chǔ)數(shù)據(jù)類型,于是便出現(xiàn)了封裝類,本文將詳細給大家介紹Java封裝類和裝箱拆箱,需要的朋友可以參考下
    2023-05-05
  • Java代碼實現(xiàn)隨機生成漢字的方法

    Java代碼實現(xiàn)隨機生成漢字的方法

    今天小編就為大家分享一篇關(guān)于Java代碼實現(xiàn)隨機生成漢字的方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • 一個Java配置文件加密解密工具類分享

    一個Java配置文件加密解密工具類分享

    在 JavaEE 配置文件中,例如 XML 或者 properties 文件,由于某些敏感信息不希望普通人員看見,則可以采用加密的方式存儲,程序讀取后進行解密
    2014-04-04

最新評論