最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Spring 單元測試中如何進(jìn)行 mock的實(shí)現(xiàn)

 更新時(shí)間:2020年12月25日 11:14:20   作者:yifanzheng  
這篇文章主要介紹了Spring 單元測試中如何進(jìn)行 mock的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

我們在使用 Spring 開發(fā)項(xiàng)目時(shí),都會用到依賴注入。如果程序依賴了外部系統(tǒng)或者不可控組件,比如依賴數(shù)據(jù)庫、網(wǎng)絡(luò)通信、文件系統(tǒng)等,我們在編寫單元測試時(shí),并不需要實(shí)際對外部系統(tǒng)進(jìn)行操作,這時(shí)就要將被測試代碼與外部系統(tǒng)進(jìn)行解耦,而這種解耦方法就叫作 “mock”。所謂 “mock” 就是用一個(gè)“假”的服務(wù)代替真正的服務(wù)。

那我們?nèi)绾蝸?mock 服務(wù)進(jìn)行單元測試呢?mock 的方式主要有兩種:手動 mock 和利用單元測試框架 mock。其中,利用框架 mock 主要是為了簡化代碼編寫。我們這里主要是介紹利用框架 mock,而手動 mock 只是簡單介紹。

手動 mock

手動 mock 其實(shí)就是重新創(chuàng)建一個(gè)類繼承被 mock 的服務(wù)類,并重寫里面的方法。在單元測試中,利用依賴注入的方式使用 mock 的服務(wù)類替換原來的服務(wù)類。具體代碼示列如下:

/**
 * UserRepository
 *
 * @author star
 */
@Repository
public class UserRepository {

  /**
   * 模擬從數(shù)據(jù)庫中獲取用戶信息,實(shí)際開發(fā)中需要連接真實(shí)的數(shù)據(jù)庫
   */
  public User getUser(String name) {
    User user = new User();
    user.setName("testing");
    user.setEmail("testing@outlook.com");

    return user;
  }
}

/**
 * MockUserRepository
 *
 * @author star
 */
public class MockUserRepository extends UserRepository {

  /**
   * 模擬從數(shù)據(jù)庫中獲取用戶信息
   */
  @Override
  public User getUser(String name) {
    User user = new User();
    user.setName("mock-test-name");
    user.setEmail("mock-test-email");

    return user;
  }
}

// 進(jìn)行單元測試
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserServiceManualTest {

  @Autowired
  private UserService userService;

  @Test
  public void testGetUser_Manual() {
    // 將 MockUserRepository 注入到 UserService 中
    userService.setUserRepository(new MockUserRepository());
    User user = userService.getUser("mock-test-name");
    Assert.assertEquals("mock-test-name", user.getName());
    Assert.assertEquals("mock-test-email", user.getEmail());
  }
}

從上面的代碼中,我們可以看到手動 mock 需要編寫大量的額外代碼,同時(shí)被測試類也需要提供依賴注入的入口(setter 方法等)。如果被 mock 的類修改了函數(shù)名稱或者功能,mock 類也要跟著修改,增加了維護(hù)成本。

為了提高效率,減少維護(hù)成本,我們推薦使用單元測是框架進(jìn)行 mock。

利用框架 mock

這里我們主要介紹 Mokito.mock()、@Mock、@MockBean 這三種方式的 mock。

Mocito.mock()

Mocito.mock() 方法允許我們創(chuàng)建類或接口的 mock 對象。然后,我們可以使用 mock 對象指定其方法的返回值,并驗(yàn)證其方法是否被調(diào)用。代碼示列如下:

@Test
public void testGetUser_MockMethod() {
  // 模擬 UserRepository,測試時(shí)不直接操作數(shù)據(jù)庫
  UserRepository mockUserRepository = Mockito.mock(UserRepository.class);
  // 將 mockUserRepository 注入到 UserService 類中
  userService.setUserRepository(mockUserRepository);

  User mockUser = mockUser();
  Mockito.when(mockUserRepository.getUser(mockUser.getName()))
      .thenReturn(mockUser);

  User user = userService.getUser(mockUser.getName());
  Assert.assertEquals(mockUser.getName(), user.getName());
  Assert.assertEquals(mockUser.getEmail(), user.getEmail());

  // 驗(yàn)證 mockUserRepository.getUser() 方法是否執(zhí)行
  Mockito.verify(mockUserRepository).getUser(mockUser.getName());
}

@Mock

@Mock 是 Mockito.mock() 方法的簡寫。同樣,我們應(yīng)該只在測試類中使用它。與 Mockito.mock() 方法不同的是,我們需要在測試期間啟用 Mockito 注解才能使用 @Mock 注解。

我們可以調(diào)用 MockitoAnnotations.initMocks(this) 靜態(tài)方法來啟用 Mockito 注解。為了避免測試之間的副作用,建議在每次測試執(zhí)行之前先進(jìn)行以下操作:

@Before
public void setup() {
  // 啟用 Mockito 注解
  MockitoAnnotations.initMocks(this);
}

我們還可以使用另一種方法來啟用 Mockito 注解。通過在 @RunWith() 指定 MockitoJUnitRunner 來運(yùn)行測試:

@RunWith(MockitoJUnitRunner.class)
public class UserServiceMockTest { 

}

下面我們來看看如何使用 @Mock 進(jìn)行服務(wù) mock。代碼示列如下:

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

  @Mock
  private UserRepository userRepository;

  @Autowired
  @InjectMocks
  private UserService userService;

  private User mockUser() {
    User user = new User();
    user.setName("mock-test-name");
    user.setEmail("mock-test-email");

    return user;
  }

  @Before
  public void setup() {
    // 啟用 Mockito 注解
    MockitoAnnotations.initMocks(this);
  }

  @Test
  public void testGetUser_MockAnnotation() {
    User mockUser = mockUser();
    Mockito.when(userRepository.getUser(mockUser.getName()))
        .thenReturn(mockUser);

    User user = userService.getUser(mockUser.getName());
    Assert.assertEquals(mockUser.getName(), user.getName());
    Assert.assertEquals(mockUser.getEmail(), user.getEmail());

    // 驗(yàn)證 mockUserRepository.getUser() 方法是否執(zhí)行
    Mockito.verify(userRepository).getUser(mockUser.getName());
  }

}

Mockito 的 @InjectMocks 注解作用是將 @Mock 所修飾的 mock 對象注入到指定類中替換原有的對象。

@MockBean

@MockBean 是 Spring Boot 中的注解。我們可以使用 @MockBean 將 mock 對象添加到 Spring 應(yīng)用程序上下文中。該 mock 對象將替換應(yīng)用程序上下文中任何現(xiàn)有的相同類型的 bean。如果應(yīng)用程序上下文中沒有相同類型的 bean,它將使用 mock 的對象作為 bean 添加到上下文中。

@MockBean 在需要 mock 特定 bean(例如外部服務(wù))的集成測試中很有用。

要使用 @MockBean 注解,我們必須在 @RunWith() 中指定 SpringRunner 來運(yùn)行測試。代碼示列如下:

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

  @MockBean
  private UserRepository userRepository;

  private User mockUser() {
    User user = new User();
    user.setName("mock-test-name");
    user.setEmail("mock-test-email");

    return user;
  }

  @Test
  public void testGetUser_MockBean() {
    User mockUser = mockUser();
    // 模擬 UserRepository
    Mockito.when(userRepository.getUser(mockUser.getName()))
        .thenReturn(mockUser);
    // 驗(yàn)證結(jié)果
    User user = userRepository.getUser(mockUser.getName());
    Assert.assertEquals(mockUser.getName(), user.getName());
    Assert.assertEquals(mockUser.getEmail(), user.getEmail());

    Mockito.verify(userRepository).getUser(mockUser.getName());
  }
}

這里需要注意的是,Spring test 默認(rèn)會重用 bean。如果 A 測試使用 mock 對象進(jìn)行測試,而 B 測試使用原有的相同類型對象進(jìn)行測試,B 測試在 A 測試之后運(yùn)行,那么 B 測試拿到的對象是 mock 的對象。一般這種情況是不期望的,所以需要用 @DirtiesContext 修飾上面的測試避免這個(gè)問題。

最后,小伙伴們可以在 GitHub 中獲取源碼

到此這篇關(guān)于Spring 單元測試中如何進(jìn)行 mock的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Spring 單元測試mock內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring MVC創(chuàng)建項(xiàng)目踩過的bug

    Spring MVC創(chuàng)建項(xiàng)目踩過的bug

    這篇文章主要介紹了Spring MVC創(chuàng)建項(xiàng)目踩過的bug,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • MybatisPlus字段類型轉(zhuǎn)換的實(shí)現(xiàn)示例

    MybatisPlus字段類型轉(zhuǎn)換的實(shí)現(xiàn)示例

    本文主要介紹了MybatisPlus如何完成字段類型轉(zhuǎn)換,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-03-03
  • java中Map如何根據(jù)key的大小進(jìn)行排序詳解

    java中Map如何根據(jù)key的大小進(jìn)行排序詳解

    這篇文章主要給大家介紹了關(guān)于java中Map如何根據(jù)key的大小進(jìn)行排序的相關(guān)資料,有時(shí)候我們業(yè)務(wù)上需要對map里面的值按照key的大小來進(jìn)行排序的時(shí)候我們就可以利用如下方法來進(jìn)行排序了,需要的朋友可以參考下
    2023-09-09
  • Spring實(shí)現(xiàn)一個(gè)簡單的SpringIOC容器

    Spring實(shí)現(xiàn)一個(gè)簡單的SpringIOC容器

    本篇文章主要介紹了Spring實(shí)現(xiàn)一個(gè)簡單的SpringIOC容器,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • 全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin選型對比

    全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin選型對比

    這篇文章主要為大家介紹了全鏈路監(jiān)控平臺Pinpoint?SkyWalking?Zipkin實(shí)現(xiàn)的選型對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2022-03-03
  • Java實(shí)現(xiàn)讀取文章中重復(fù)出現(xiàn)的中文字符串

    Java實(shí)現(xiàn)讀取文章中重復(fù)出現(xiàn)的中文字符串

    本文主要介紹了Java實(shí)現(xiàn)讀取文章中重復(fù)出現(xiàn)的中文字符串的方法。具有很好的參考價(jià)值。下面跟著小編一起來看下吧
    2017-03-03
  • Java編程實(shí)現(xiàn)游戲中的簡單碰撞檢測功能示例

    Java編程實(shí)現(xiàn)游戲中的簡單碰撞檢測功能示例

    這篇文章主要介紹了Java編程中的簡單碰撞檢測功能,涉及java針對坐標(biāo)點(diǎn)的相關(guān)數(shù)學(xué)運(yùn)算操作技巧,需要的朋友可以參考下
    2017-10-10
  • kafka的消息存儲機(jī)制和原理分析

    kafka的消息存儲機(jī)制和原理分析

    這篇文章主要介紹了kafka的消息存儲機(jī)制和原理,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • spring boot加載資源路徑配置和classpath問題解決

    spring boot加載資源路徑配置和classpath問題解決

    這篇文章主要介紹了spring boot加載資源路徑配置和classpath問題解決,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-03-03
  • Mybatis中3種關(guān)聯(lián)關(guān)系的實(shí)現(xiàn)方法示例

    Mybatis中3種關(guān)聯(lián)關(guān)系的實(shí)現(xiàn)方法示例

    這篇文章主要給大家介紹了關(guān)于Mybatis中3種關(guān)聯(lián)關(guān)系的實(shí)現(xiàn)方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用Mybatis具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-11-11

最新評論

那曲县| 随州市| 昌江| 兴城市| 曲松县| 通城县| 视频| 海口市| 赣州市| 呼图壁县| 会宁县| 息烽县| 新巴尔虎左旗| 尚志市| 日喀则市| 台南县| 疏勒县| 江西省| 霍林郭勒市| 溆浦县| 明溪县| 白朗县| 黄大仙区| 安达市| 日土县| 平乡县| 镇坪县| 桦甸市| 龙岩市| 顺义区| 苍山县| 旬邑县| 高尔夫| 涟水县| 禄丰县| 白玉县| 南康市| 黑龙江省| 枣庄市| 淄博市| 光泽县|