国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

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

瀏覽:44日期:2023-07-27 17:23:37

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

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

手動(dòng) mock

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

/** * UserRepository * * @author star */@Repositorypublic class UserRepository { /** * 模擬從數(shù)據(jù)庫(kù)中獲取用戶(hù)信息,實(shí)際開(kāi)發(fā)中需要連接真實(shí)的數(shù)據(jù)庫(kù) */ 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ù)庫(kù)中獲取用戶(hù)信息 */ @Override public User getUser(String name) { User user = new User(); user.setName('mock-test-name'); user.setEmail('mock-test-email'); return user; }}// 進(jìn)行單元測(cè)試@RunWith(SpringRunner.class)@SpringBootTestpublic 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()); }}

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

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

利用框架 mock

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

Mocito.mock()

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

@Testpublic void testGetUser_MockMethod() { // 模擬 UserRepository,測(cè)試時(shí)不直接操作數(shù)據(jù)庫(kù) UserRepository mockUserRepository = Mockito.mock(UserRepository.class); // 將 mockUserRepository 注入到 UserService 類(lèi)中 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() 方法的簡(jiǎn)寫(xiě)。同樣,我們應(yīng)該只在測(cè)試類(lèi)中使用它。與 Mockito.mock() 方法不同的是,我們需要在測(cè)試期間啟用 Mockito 注解才能使用 @Mock 注解。

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

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

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

@RunWith(MockitoJUnitRunner.class)public class UserServiceMockTest { }

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

@RunWith(SpringRunner.class)@SpringBootTestpublic 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 對(duì)象注入到指定類(lèi)中替換原有的對(duì)象。

@MockBean

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

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

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

@RunWith(SpringRunner.class)@SpringBootTestpublic 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)會(huì)重用 bean。如果 A 測(cè)試使用 mock 對(duì)象進(jìn)行測(cè)試,而 B 測(cè)試使用原有的相同類(lèi)型對(duì)象進(jìn)行測(cè)試,B 測(cè)試在 A 測(cè)試之后運(yùn)行,那么 B 測(cè)試拿到的對(duì)象是 mock 的對(duì)象。一般這種情況是不期望的,所以需要用 @DirtiesContext 修飾上面的測(cè)試避免這個(gè)問(wèn)題。

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

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

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 97青娱国产盛宴精品视频 | 国产成人精品一区二区视频 | 午夜剧场福利社 | 欧美日韩在线观看一区二区 | 欧美高清性色生活片免费观看 | 国产在线精品一区二区中文 | 欧美高清正版在线 | 欧美亚洲综合另类在线观看 | 悟空影视大全免费高清 | 99re6这里有精品热视频在线 | 成人区精品一区二区不卡亚洲 | 免费人成年短视频在线观看免费网站 | 日本特级视频 | 成人区精品一区二区不卡亚洲 | 精品视频自拍 | 久久橹 | 国产欧美一区二区成人影院 | cao在线观看 | 成人毛片视频免费网站观看 | 日韩国产精品99久久久久久 | 日韩1页| 久草视频在线免费播放 | 交视频在线观看国产网站 | 久久精品国产只有精品6 | 99久久精品国产亚洲 | 亚洲综合亚洲综合网成人 | 欧美怡红院免费的视频 | 日本加勒比高清一本大道 | 日韩精品一区二区三区视频网 | 特黄aa级毛片免费视频播放 | 亚洲一级毛片免观看 | 成人国产精品免费视频 | 怡红院精品视频 | 日韩一区二区三区免费视频 | 国产三级午夜理伦三级 | 亚洲久久天堂 | 国内精品线在线观看 | 欧美在线精品一区二区三区 | 男女午夜| 91香蕉国产线在线观看免费 | 亚洲精品一区二区在线观看 |