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

SpringBoot中Mockito單元測試入門

 更新時間:2021年06月01日 10:34:12   作者:小小工匠  
單元測試在很多地方都用的到,本文主要介紹了SpringBoot中Mockito單元測試入門,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

Mock 測試

Mock 測試就是在測試過程中,創(chuàng)建一個假的對象,避免你為了測試一個方法,卻要自行構(gòu)建整個 Bean 的依賴鏈。

舉個例子:

類 A 需要調(diào)用類 B 和類 C,而類 B 和類 C 又需要調(diào)用其他類如 D、E、F 等,假設(shè)類 D 是一個外部服務(wù),那就會很難測,因為你的返回結(jié)果會直接的受外部服務(wù)影響,導(dǎo)致你的單元測試可能今天會過、但明天就過不了了。

在這里插入圖片描述

而當(dāng)我們引入 Mock 測試時,就可以創(chuàng)建一個假的對象,替換掉真實的 Bean B 和 C,這樣在調(diào)用B、C的方法時,實際上就會去調(diào)用這個假的 Mock 對象的方法,而我們就可以自己設(shè)定這個 Mock 對象的參數(shù)和期望結(jié)果,讓我們可以專注在測試當(dāng)前的類 A,而不會受到其他的外部服務(wù)影響,這樣測試效率就能提高很多。

在這里插入圖片描述

What's Mockito

Mockito 是一種 Java Mock 框架,主要就是用來做 Mock 測試的,它可以模擬任何 Spring 管理的 Bean、模擬方法的返回值、模擬拋出異常等等,同時也會記錄調(diào)用這些模擬方法的參數(shù)、調(diào)用順序,從而可以校驗出這個 Mock 對象是否有被正確的順序調(diào)用,以及按照期望的參數(shù)被調(diào)用。

像是 Mockito 可以在單元測試中模擬一個 Service 返回的數(shù)據(jù),而不會真正去調(diào)用該 Service,通過模擬一個假的 Service 對象,來快速的測試當(dāng)前想要測試的類。

目前在 Java 中主流的 Mock 測試工具有 Mockito、JMock、EasyMock等等,而 SpringBoot 目前默認(rèn)的測試框架是 Mockito 框架。

使用 Mockito

pom依賴

 <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>

在這里插入圖片描述

Demo Code

一個 UserService,兩個方法

  • getUserById() -------------> 調(diào)用 UserDao 這個 bean的 getUserById()
  • insertUser() -------------> 調(diào)用 UserDao 這個 bean的 insertUser()
@Component
public class UserService {
    
    @Autowired
    private UserDao userDao;

    public User getUserById(Integer id) {
        return userDao.getUserById(id);
    }

    public Integer insertUser(User user) {
        return userDao.insertUser(user);
    }
}

【POJO對象】

public class User {
    private Integer id;
    private String name;
    //省略 getter/setter
}

【常規(guī)操作】

如果這時候我們先不使用 Mockito 模擬一個假的 userDao Bean,而是真的去調(diào)用一個正常的 Spring Bean 的 userDao 的話, 注入 userService Bean,然后去調(diào)用方法,而他會再去調(diào)用 userDao 取得數(shù)據(jù)庫的數(shù)據(jù),然后我們再對返回結(jié)果做 Assert 斷言檢查。

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceTest {

    //先普通的注入一個userService bean
    @Autowired
    private UserService userService;

    @Test
    public void getUserById() throws Exception {
        //普通的使用userService,他里面會再去調(diào)用userDao取得數(shù)據(jù)庫的數(shù)據(jù)
        User user = userService.getUserById(1);
        
        //檢查結(jié)果
        Assert.assertNotNull(user);
        Assert.assertEquals(user.getId(), new Integer(1));
        Assert.assertEquals(user.getName(), "John");
    }
}

【Mockito】

但是如果 userDao 還沒寫好,又想先測 userService 的話,就需要使用 Mockito 去模擬一個假的 userDao 出來。

具體怎么搞呢?

在 userDao 上加上一個 @MockBean 注解

當(dāng) userDao 被加上這個注解之后,表示 Mockito 會幫我們創(chuàng)建一個假的 Mock 對象,替換掉 Spring 中已存在的那個真實的 userDao Bean,也就是說,注入進(jìn) userService 的 userDao Bean,已經(jīng)被我們替換成假的 Mock 對象了,所以當(dāng)我們再次調(diào)用 userService 的方法時,會去調(diào)用的實際上是 mock userDao Bean 的方法,而不是真實的 userDao Bean。

當(dāng)我們創(chuàng)建了一個假的 userDao 后,我們需要為這個 mock userDao 自定義方法的返回值,這里有一個公式用法,下面這段代碼的意思為,當(dāng)調(diào)用了某個 Mock 對象的方法時,就回傳我們想要的自定義結(jié)果。

Mockito.when( 對象.方法名() ).thenReturn( 自定義結(jié)果 )

代碼如下:

@RunWith(SpringRunner.class)
@SpringBootTest
publicclass UserServiceTest {
    
    @Autowired
    private UserService userService;
    
    @MockBean
    private UserDao userDao;

    @Test
    public void getUserById() throws Exception {
        // 定義當(dāng)調(diào)用mock userDao的getUserById()方法,并且參數(shù)為3時,就返回id為200、name為I'm mock3的user對象
        Mockito.when(userDao.getUserById(3)).thenReturn(new User(200, "Aritisan"));
        
        // 返回的會是名字為I'm mock 3的user對象
        User user = userService.getUserById(1);

        Assert.assertNotNull(user);
        Assert.assertEquals(user.getId(), new Integer(200));
        Assert.assertEquals(user.getName(), "Aritisan");
    }
}

Mockito 除了最基本的 Mockito.when( 對象.方法名() ).thenReturn( 自定義結(jié)果 ),還提供了其他用法讓我們使用。

thenReturn

當(dāng)使用任何整數(shù)值調(diào)用 userService 的 getUserById() 方法時,就回傳一個名字為Aritisan的 User 對象。

Mockito.when(userService.getUserById(Mockito.anyInt())).thenReturn(new User(3, "Aritisan"));
User user1 = userService.getUserById(3); // 回傳的user的名字為Aritisan
User user2 = userService.getUserById(200); // 回傳的user的名字也為Aritisan

限制只有當(dāng)參數(shù)的數(shù)字是 3 時,才會回傳名字為 Aritisan 的 user 對象。

Mockito.when(userService.getUserById(3)).thenReturn(new User(3, "Aritisan"));
User user1 = userService.getUserById(3); // 回傳的user的名字為Aritisan
User user2 = userService.getUserById(200); // 回傳的user為null

當(dāng)調(diào)用 userService 的 insertUser() 方法時,不管傳進(jìn)來的 user 是什么,都回傳 100。

Mockito.when(userService.insertUser(Mockito.any(User.class))).thenReturn(100);
Integer i = userService.insertUser(new User()); //會返回100

thenThrow

當(dāng)調(diào)用 userService 的 getUserById() 時的參數(shù)是 9 時,拋出一個 RuntimeException。

Mockito.when(userService.getUserById(9)).thenThrow(new RuntimeException("mock throw exception"));
User user = userService.getUserById(9); //會拋出一個RuntimeException

如果方法沒有返回值的話(即是方法定義為 public void myMethod() {…}),要改用 doThrow() 拋出 Exception。

Mockito.doThrow(new RuntimeException("mock throw  exception")).when(userService).print();
userService.print(); //會拋出一個RuntimeException

verify

檢查調(diào)用 userService 的 getUserById()、且參數(shù)為3的次數(shù)是否為1次。

驗證調(diào)用順序,驗證 userService 是否先調(diào)用 getUserById() 兩次,并且第一次的參數(shù)是 3、第二次的參數(shù)是 5,然后才調(diào)用insertUser() 方法。

InOrder inOrder = Mockito.inOrder(userService);
inOrder.verify(userService).getUserById(3);
inOrder.verify(userService).getUserById(5);
inOrder.verify(userService).insertUser(Mockito.any(User.class));

Mockito 注意事項

上述就是 Mockito 的 Mock 對象使用方法,不過當(dāng)使用 Mockito 在 Mock 對象時,有一些限制需要遵守:

  • 不能 Mock 靜態(tài)方法
  • 不能 Mock private 方法
  • 不能 Mock final class

因此在寫代碼時,需要做良好的功能拆分,才能夠使用 Mockito 的 Mock 技術(shù),幫助我們降低測試時 Bean 的耦合度。

到此這篇關(guān)于SpringBoot中Mockito單元測試入門的文章就介紹到這了,更多相關(guān)SpringBoot Mockito單元測試 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring Cloud OAuth2 實現(xiàn)用戶認(rèn)證及單點登錄的示例代碼

    Spring Cloud OAuth2 實現(xiàn)用戶認(rèn)證及單點登錄的示例代碼

    這篇文章主要介紹了Spring Cloud OAuth2 實現(xiàn)用戶認(rèn)證及單點登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-10-10
  • Java TreeSet類的簡單理解和使用

    Java TreeSet類的簡單理解和使用

    這篇文章主要介紹了Java TreeSet類的簡單理解和使用,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-02-02
  • 一文徹底搞定Java中常用集合的排序方法

    一文徹底搞定Java中常用集合的排序方法

    在某些特殊的場景下我們需要在Java程序中對List集合進(jìn)行排序操作,下面這篇文章主要給大家介紹了關(guān)于Java中常用集合的排序方法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-11-11
  • Idea中添加Maven項目支持scala的詳細(xì)步驟

    Idea中添加Maven項目支持scala的詳細(xì)步驟

    這篇文章主要介紹了Idea中添加Maven項目支持scala,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-03-03
  • @Schedule?如何解決定時任務(wù)推遲執(zhí)行

    @Schedule?如何解決定時任務(wù)推遲執(zhí)行

    這篇文章主要介紹了@Schedule?如何解決定時任務(wù)推遲執(zhí)行問題。具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-09-09
  • java實現(xiàn)屏幕共享功能實例分析

    java實現(xiàn)屏幕共享功能實例分析

    這篇文章主要介紹了java實現(xiàn)屏幕共享功能的方法,以實例形式分析了屏幕共享功能的客戶端與服務(wù)端的詳細(xì)實現(xiàn)方法,是非常具有實用價值的技巧,需要的朋友可以參考下
    2014-12-12
  • SpringBoot解決mysql連接8小時問題

    SpringBoot解決mysql連接8小時問題

    服務(wù)連接mysql數(shù)據(jù)庫,8小時沒有數(shù)據(jù)庫的操作時候,數(shù)據(jù)庫會主動斷開連接釋放資源,本文就詳細(xì)的介紹一下解決方法,感興趣的可以了解一下
    2023-08-08
  • Java 異步回調(diào)機(jī)制實例分析

    Java 異步回調(diào)機(jī)制實例分析

    這篇文章主要介紹了Java 異步回調(diào)機(jī)制實例解析的相關(guān)資料,需要的朋友可以參考下
    2017-02-02
  • Java網(wǎng)絡(luò)編程三要素及通信程序詳解

    Java網(wǎng)絡(luò)編程三要素及通信程序詳解

    這篇文章主要介紹了Java網(wǎng)絡(luò)編程三要素及通信程序詳解,Java網(wǎng)絡(luò)編程是在網(wǎng)絡(luò)通信協(xié)議下,實現(xiàn)網(wǎng)絡(luò)互連的不同計算機(jī)上運行的程序間可以進(jìn)行數(shù)據(jù)交換,需要的朋友可以參考下
    2023-07-07
  • RocketMQ源碼分析之Broker過期消息清理機(jī)制

    RocketMQ源碼分析之Broker過期消息清理機(jī)制

    這篇文章主要為大家介紹了RocketMQ源碼分析之Broker過期消息清理機(jī)制示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05

最新評論