日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術文章
文章詳情頁

Spring 單元測試中如何進行 mock的實現

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

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

那我們如何來 mock 服務進行單元測試呢?mock 的方式主要有兩種:手動 mock 和利用單元測試框架 mock。其中,利用框架 mock 主要是為了簡化代碼編寫。我們這里主要是介紹利用框架 mock,而手動 mock 只是簡單介紹。

手動 mock

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

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

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

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

利用框架 mock

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

Mocito.mock()

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

@Testpublic void testGetUser_MockMethod() { // 模擬 UserRepository,測試時不直接操作數據庫 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()); // 驗證 mockUserRepository.getUser() 方法是否執行 Mockito.verify(mockUserRepository).getUser(mockUser.getName());}

@Mock

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

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

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

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

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

下面我們來看看如何使用 @Mock 進行服務 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()); // 驗證 mockUserRepository.getUser() 方法是否執行 Mockito.verify(userRepository).getUser(mockUser.getName()); }}

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

@MockBean

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

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

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

@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); // 驗證結果 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 默認會重用 bean。如果 A 測試使用 mock 對象進行測試,而 B 測試使用原有的相同類型對象進行測試,B 測試在 A 測試之后運行,那么 B 測試拿到的對象是 mock 的對象。一般這種情況是不期望的,所以需要用 @DirtiesContext 修飾上面的測試避免這個問題。

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

到此這篇關于Spring 單元測試中如何進行 mock的實現的文章就介紹到這了,更多相關Spring 單元測試mock內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Spring
相關文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产精品一区二区免费福利视频| 中文字幕日韩亚洲| 欧美日韩精品一本二本三本 | 欧美精品观看| 99久精品视频在线观看视频| 精品欧美视频| 日韩中文在线播放| 福利一区二区三区视频在线观看| 人人爱人人干婷婷丁香亚洲| 国产在线日韩| 私拍精品福利视频在线一区| 日本综合字幕| 国产黄大片在线观看| 国产精品永久| se01亚洲视频| 亚洲精华国产欧美| 国产一区观看| av亚洲在线观看| 亚洲va中文在线播放免费| 成人台湾亚洲精品一区二区| 你懂的国产精品| 你懂的国产精品| 欧美极品中文字幕| 精品日本视频| 国产高清不卡| 99精品综合| 亚洲黄色影院| 亚洲一区欧美二区| 在线亚洲观看| 99国产精品视频免费观看一公开 | 国产一区日韩欧美| 99久精品视频在线观看视频| 国产专区一区| 丝袜诱惑制服诱惑色一区在线观看| 99在线观看免费视频精品观看| 国产麻豆综合| 亚洲精选久久| 欧美一区不卡| 国产精品成人一区二区不卡| 日精品一区二区三区| 日韩在线卡一卡二| 在线视频精品| 欧美日韩一区二区三区视频播放| 999国产精品视频| 日韩视频精品在线观看| 亚洲一区久久| 97se亚洲| 电影91久久久| 激情欧美一区| 综合激情在线| 免费一级欧美片在线观看网站| 国产精品高颜值在线观看| 91精品一区国产高清在线gif | 美女精品网站| 日韩精品视频一区二区三区| 国产日韩中文在线中文字幕| 麻豆国产精品视频| se01亚洲视频| 在线国产精品一区| 国产精品**亚洲精品| 性感美女一区二区在线观看| 亚洲在线一区| 国产精品xvideos88| 日本欧美不卡| 日韩伦理一区| 欧美日韩国产在线观看网站| 蜜桃视频第一区免费观看| 丝袜亚洲精品中文字幕一区| 国产欧美视频在线| 久久天堂精品| 蜜臀av在线播放一区二区三区| 日韩精品一页| 韩日一区二区| 不卡中文一二三区| 国产欧美日韩影院| 久久中文视频| 91精品啪在线观看国产爱臀| 成人污污视频| 日韩制服丝袜av| 高清久久精品| 亚洲男人在线| 伊人久久视频| 日韩视频久久| 欧美日韩1区| 婷婷成人综合| 国产精品欧美三级在线观看| 亚洲精品成人| 久久精品亚洲一区二区| 国产亚洲毛片在线| 精品美女视频| 最新国产精品久久久| 天堂√中文最新版在线| 少妇精品在线| 亚洲一级黄色| 精品中文字幕一区二区三区四区| 国产视频亚洲| 国产成人免费精品| 久久中文字幕一区二区| 欧美日韩激情| 精品一区二区三区中文字幕视频| 久色成人在线| 成人在线网站| 国产精品久久亚洲不卡| 亚洲深夜影院| 九色porny丨国产首页在线| 欧美一区在线观看视频| 欧美日韩国产精品一区二区亚洲| 精品国产不卡| 日韩av一级片| 一本色道久久精品| 日韩高清中文字幕一区二区| 国产精品久久久免费| 午夜久久福利| 欧美成人a交片免费看| 国产精品一区亚洲| 亚洲精品影视| 快she精品国产999| 久久黄色影院| 97精品国产一区二区三区| 日韩av中文在线观看| 天堂资源在线亚洲| 欧美激情日韩| 欧美在线黄色| 视频在线观看一区二区三区| 久久精品青草| 日韩毛片视频| 91偷拍一区二区三区精品| 日韩精品视频一区二区三区| 午夜国产精品视频| 国产一区久久| 日韩三区在线| 亚洲播播91| 日韩在线观看一区| 高清一区二区三区| 亚洲三区欧美一区国产二区| 女人av一区| 欧美亚洲在线日韩| 肉色欧美久久久久久久免费看 | 精品国产一区二区三区2021| 青草国产精品久久久久久| 婷婷精品在线| 久久亚洲风情| 美女日韩在线中文字幕| 五月综合激情| 亚洲成人免费| 不卡中文字幕| 日韩天堂av| 国产精品日本欧美一区二区三区| 亚洲深爱激情| 久久人人88| 女主播福利一区| 亚洲资源av| 视频一区在线播放| 亚洲视频国产精品| 亚洲丝袜美腿一区| 日本亚洲三级在线| 蜜臀久久99精品久久久画质超高清| 亚洲一区二区三区高清不卡| 老鸭窝毛片一区二区三区| 亚洲一级大片| 日韩精品a在线观看91| 日本欧美大码aⅴ在线播放| 国产欧美一区二区三区米奇| 久久av中文| 91视频一区| 99久久九九| 国产精品毛片在线| 日韩三区四区| 国产精品白丝久久av网站| 精品国产欧美日韩| 久久久久.com| 国产超碰精品| 久久久久久久久丰满| 欧美日韩少妇| 视频在线观看91| 亚洲婷婷丁香| 国产精品**亚洲精品| 日韩高清一级| 国产福利亚洲| 欧美精品一线| 久久免费视频66| 日韩制服丝袜先锋影音| 色乱码一区二区三区网站| 免费一区二区视频| www.51av欧美视频| 日韩中文av| 亚洲女同av| 久久国产精品免费一区二区三区 | 另类国产ts人妖高潮视频| 久久女人天堂| 亚洲一二三区视频| 1024精品一区二区三区| 国产精品美女午夜爽爽| 亚洲欧美日韩国产一区| а√天堂8资源中文在线| 18国产精品| 国产精品日韩久久久| 国产欧洲在线| 国产精品手机在线播放| 亚洲激情av|