您現在的位置是:首頁 > 運動
單元測試不再怕!一文學會SpringBoot單元測試
springboot測試類怎麼寫
註解相關
@SpringBootTest
SpringBoot應用程式專用的測試註解,SpringBoot程式的入口是Bootstrap類,所以SpringBoot專門提供了一個@SpringBootTest註解測試Bootstrap類。該註解也可以引用Bootstrap類的配置,因為所有配置都會透過Bootstrap類去載入。
在 Spring Boot 中,@SpringBootTest 註解主要用於測試基於自動配置的 ApplicationContext,它允許我們設定測試上下文中的 Servlet 環境。
@SpringBootTest註解中的webEnvironment可以有四個選項:
MOCK:載入 WebApplicationContext 並提供一個 Mock 的 Servlet 環境,此時內建的 Servlet 容器並沒有正式啟動。
RANDOM_PORT:載入 EmbeddedWebApplicationContext 並提供一個真實的 Servlet 環境,然後使用一個隨機埠啟動內建容器。
DEFINED_PORT:這個配置也是透過載入 EmbeddedWebApplicationContext 提供一個真實的 Servlet 環境,但使用的是預設埠,如果沒有配置埠就使用 8080。
NONE:載入 ApplicationContext 但並不提供任何真實的 Servlet 環境。
在多數場景下,一個真實的 Servlet 環境對於測試而言過於重量級,透過 MOCK 環境則可以緩解這種環境約束所帶來的困擾
@RunWith註解與SpringRunner
JUnit框架提供的用於設定測試執行器的基礎註解。
我們可以透過 @RunWith(SpringRunner。class) 讓測試運行於Spring測試環境。
SpringRunner 繼承 SpringJUnit4ClassRunner 其實他們是一樣的,就是執行在spring環境,它允許 JUnit 和 Spring TestContext 整合執行,而 Spring TestContext 則提供了用於測試 Spring 應用程式的各項通用的支援功能。
@Test
JUnit 中使用的基礎測試註解,用來表明需要執行的測試用例
@DataJpaTest
專門用於測試關係型資料庫的測試註解
@DataJpaTest 註解會自動注入各種 Repository 類,即是持久化bean,並初始化一個記憶體資料庫和及訪問該資料庫的資料來源。
在測試場景下,一般我們可以使用 H2 作為記憶體資料庫,並透過 MySQL 實現資料持久化
@MockBean
用於實現Mock機制的測試註解
自動用 Mockito 模擬替換應用程式上下文中相同型別的 bean。
@WebMvcTest
在 Web 容器環境中嵌入 MockMvc 的註解
@SpringBootTest 註解不能和 @WebMvcTest 註解同時使用。
該註解將初始化測試 Controller 所必需的 Spring MVC 基礎設施
controllers 引數設定為 XxxController。class,告訴 Spring Boot 將為此測試建立的應用程式上下文限制為給定的控制器 bean 和該bean相關的一些 Spring Web MVC 所需的一些框架 bean。
MockMvc類提供的基礎方法分為以下6 種
Perform:執行一個 RequestBuilder 請求,會自動執行 SpringMVC 流程並對映到相應的 Controller 進行處理。
get/post/put/delete:聲明發送一個 HTTP 請求的方式,根據 URI 模板和 URI 變數值得到一個 HTTP 請求,支援 GET、POST、PUT、DELETE 等 HTTP 方法。
param:新增請求引數,傳送 JSON 資料時將不能使用這種方式,而應該採用 @ResponseBody 註解。
andExpect:新增 ResultMatcher 驗證規則,透過對返回的資料進行判斷來驗證 Controller 執行結果是否正確。
andDo:新增 ResultHandler 結果處理器,比如除錯時列印結果到控制檯。
andReturn:最後返回相應的 MvcResult,然後執行自定義驗證或做非同步處理。
@AutoConfigureMockMvc
@AutoConfigureMockMvc與@SpringBootTest 組合嵌入MockMvc的註解,在使用 @SpringBootTest 註解的場景下,如果我們想使用 MockMvc 物件,那麼可以引入 @AutoConfigureMockMvc 註解。
透過將 @SpringBootTest 註解與 @AutoConfigureMockMvc 註解相結合,@AutoConfigureMockMvc 註解將透過 @SpringBootTest 載入的 Spring 上下文環境中自動配置 MockMvc 這個類。
註解名稱
註解描述
@SpringBootTest
Spring Boot 應用程式專用的測試註解
@RunWith
JUnit 框架提供的用於設定測試執行器的基礎註解
@Test
JUnit 中使用的基礎測試註解,用來表明需要執行的測試用例
@DataJpaTest
專門用於測試關係型資料庫的測試註解
@MockBea
用於實現 Mock 機制的測試註解
@WebMvcTest
在 Web 容器環境中嵌入 MockMvc 的註解
@AutoConfigureMockMvc
與@SpringBootTest組合嵌入MockMvc的註解
相關說明
TestEntityManager
它的效果相當於不使用真正的 XxxRepository(即是持久化bean) 完成資料的持久化,從而提供了一種資料與環境之間的隔離機制。
TestRestTemplate
Spring Boot 提供的 TestRestTemplate 發起請求的方式與 RestTemplate完全一致,只不過它專門用在測試環境中。
如果我們想在測試環境中使用 @SpringBootTest,則可以直接使用 TestRestTemplate 來測試遠端訪問過程
@SpringBootTest 註解透過使用 SpringBootTest。WebEnvironment。RANDOM_PORT 指定了隨機埠的 Web 執行環境。然後,我們基於 TestRestTemplate 發起了 HTTP 請求並驗證了結果。
Mock 機制
Mock 的意思是模擬,它可以用來對系統、元件或類進行隔離。
在測試過程中,我們通常關注測試物件本身的功能和行為,而對測試物件涉及的一些依賴,僅僅關注它們與測試物件之間的互動(比如是否呼叫、何時呼叫、呼叫的引數、呼叫的次數和順序,以及返回的結果或發生的異常等),並不關注這些被依賴物件如何執行這次呼叫的具體細節。因此,Mock 機制就是使用 Mock 物件替代真實的依賴物件,並模擬真實場景來開展測試工作
@SpringBootTest 註解中的 SpringBootTest。WebEnvironment。MOCK 選項,該選項用於載入WebApplicationContext 並提供一個 Mock 的 Servlet 環境,內建的 Servlet 容器並沒有真實啟動。
測試實戰
前提
初始化資料
DELETE FROM user;INSERT INTO user (id, name, age, email)VALUES (1, ‘Jone’, 18, ‘test1@baomidou。com’), (2, ‘Jack’, 20, ‘test2@baomidou。com’), (3, ‘Tom’, 28, ‘test3@baomidou。com’), (4, ‘Sandy’, 21, ‘test4@baomidou。com’), (5, ‘Billie’, 24, ‘test5@baomidou。com’);複製程式碼
pom依賴
<!——我們需要一個web應用——>
注意:在src/main/resources/下放置mysql的配置,而在src/test/resources/下放置h2的配置,springboot自動幫助我們在不同的環境執行不同的配置檔案
實體類
/** * @Description: 實體類 * GenerationType: * TABLE:使用一個特定的資料庫表格來儲存主鍵。 * SEQUENCE:根據底層資料庫的序列來生成主鍵,條件是資料庫支援序列。 * IDENTITY:主鍵由資料庫自動生成(主要是自動增長型) * AUTO:主鍵由程式控制選擇上面的一個策略。 * @Author: jianweil * @date: 2021/11/22 17:29 */@Entity@AllArgsConstructor@NoArgsConstructor@Data//@Proxy(lazy = false)public class User { @Id //配置了h2GenerationType。AUTO程式幫助我們使用了GenerationType。SEQUENCE //@GeneratedValue(strategy = GenerationType。AUTO) //序列化 //@GeneratedValue(strategy = GenerationType。SEQUENCE) // https://www。cnblogs。com/hongchengshise/p/10612301。html //資料庫自增 @GeneratedValue(strategy = GenerationType。IDENTITY) private Long id; @Column private String name; @Column private Integer age; @Column private String email;}複製程式碼
測試持久層-dao
方法1。 @DataJpaTest
測試持久化類我們一般使用@DataJpaTest+@RunWith(SpringRunner。class)註解
@DataJpaTest 註解會自動注入各種 Repository 類,並初始化一個記憶體資料庫和及訪問該資料庫的資料來源。
在測試場景下,用@DataJpaTest 註解的測試使用嵌入式記憶體資料庫。我們可以使用 H2 作為記憶體資料庫
它與@RunWith(SpringRunner。class)結合使用。 該註解會禁用完全自動配置,並且僅應用與 JPA 測試相關的配置。
由於H2啟動初始化5條記錄到記憶體資料庫,所以user1插入的id為6
@RunWith(SpringRunner。class)@DataJpaTestpublic class TestDao { /** * 效果相當於不使用真正的 UserRepository 完成資料的持久化,從而提供了一種資料與環境之間的隔離機制。 */ @Autowired private TestEntityManager entityManager; @Autowired private UserRepository userRepository; /** * @throws Exception */ @Test public void testGetById() throws Exception { String expected = “new6@qq。com”; User user1 = new User(); user1。setName(“new6”); user1。setAge(6); user1。setEmail(expected); //User user3 = this。userRepository。save(user1); //User的id自增策略 IDENTITY策略:用初始化好資料的h2資料庫儲存 id=6 //User的id自增策略 SEQUENCE策略:使用新的空的h2資料庫儲存 id=1 //與上面效果一樣 this。entityManager。persist(user1); User user2 = new User(); user2。setName(“new7”); user2。setAge(7); user2。setEmail(“new7@qq。com”); //User user4 = this。userRepository。save(user2); this。entityManager。persist(user2); User user6 = this。userRepository。getById(6L); User user7 = this。userRepository。getById(7L); Assert。assertNotNull(user6); Assert。assertEquals(expected, user6。getEmail()); Assert。assertEquals(“new7@qq。com”, user7。getEmail()); }}複製程式碼
測試業務層-Service
方法1。 使用Mock機制模擬資料
Mock 機制就是使用 Mock 物件替代真實的依賴物件,並模擬真實場景來開展測試工作。
@SpringBootTest 註解中的 SpringBootTest。WebEnvironment。MOCK 選項,該選項用於載入WebApplicationContext 並提供一個 Mock 的 Servlet 環境,內建的 Servlet 容器並沒有真實啟動。
首先,我們透過 @MockBean 註解注入了 userRepository,即是告訴程式我準備虛擬這個類
然後,基於第三方 Mock 框架 Mockito 提供的 when/thenReturn 機制完成了對 userRepository 中 getById() 方法的 Mock。即是告訴程式我虛擬這個類的這個方法了,你不要去真實資料庫查了,用我這個返回
@RunWith(SpringRunner。class)@SpringBootTest(webEnvironment = SpringBootTest。WebEnvironment。MOCK)public class TestServiceMock { /** * @MockBean使資料隔離 */ @MockBean private UserRepository userRepository; @Resource private UserService userService; @Test public void testGetById() throws Exception { Long id = 22L; //用Mock構建測試方法userService。findById(22L)需要的userRepository。getById(id)的資料, Mockito。when(userRepository。getById(id))。thenReturn(new User(22L, “MockBean”, 22, “MockBean@qq。com”)); User user = userService。findById(22L); Assert。assertNotNull(user); Assert。assertEquals(“MockBean”, user。getName()); }}複製程式碼
方法2。 直接測試資料庫
如果你希望在測試用例中直接注入真實的userRepository,這時就可以使用@SpringBootTest 註解中的 SpringBootTest。WebEnvironment。RANDOM_PORT 選項
SpringBootTest。WebEnvironment。RANDOM_PORT:以一個隨機的埠啟動整個 Spring Boot 工程,並從資料庫中(H2)真實獲取目標資料進行驗證。
@RunWith(SpringRunner。class)@SpringBootTest(webEnvironment = SpringBootTest。WebEnvironment。RANDOM_PORT)public class TestServiceNoMock { /** * 注入真正資料庫 */ @Resource private UserService userService; /** * 報錯沒有seesion是jpa框架導致,解決有: * 1。 加事務註解 @Transactional * 2。 實體類加@Proxy(lazy = false) * 3。 配置檔案加spring。jpa。properties。hibernate。enable_lazy_load_no_trans=true * * @throws Exception */ @Test @Transactional public void testGetById() throws Exception { Long id = 1L; User user = userService。findById(id); Assert。assertNotNull(user); Assert。assertEquals(“Jone”, user。getName()); }}複製程式碼
測試控制層-Controller
方法1。@SpringBootTest+TestRestTemplate+ @MockBean
@SpringBootTest 註解透過使用 SpringBootTest。WebEnvironment。RANDOM_PORT 指定了隨機埠的 Web 執行環境。
如果我們想在測試環境中使用 @SpringBootTest,則可以直接使用 TestRestTemplate 來測試遠端訪問過程
Spring Boot 提供的 TestRestTemplate 與 RestTemplate 非常類似,只不過它專門用在測試環境中。
@RunWith(SpringRunner。class)@SpringBootTest(webEnvironment = SpringBootTest。WebEnvironment。RANDOM_PORT)public class TestController { @Autowired private TestRestTemplate testRestTemplate; @MockBean private UserService userService; @Test public void testGetById() throws Exception { Long userId = 1L; given(this。userService。findById(userId)) 。willReturn(new User(1L, “MockBean”, 44, “MockBean@qq。com”)); //postForObject是post請求 ResponseEntity
方法2。@SpringBootTest+@AutoConfigureMockMvc+ @MockBean
在使用 @SpringBootTest 註解的場景下,如果我們想使用 MockMvc 物件,那麼可以引入 @AutoConfigureMockMvc 註解。
透過將 @SpringBootTest 註解與 @AutoConfigureMockMvc 註解相結合,@AutoConfigureMockMvc 註解將透過 @SpringBootTest 載入的 Spring 上下文環境中自動配置 MockMvc 這個類。
@RunWith(SpringRunner。class)@SpringBootTest@AutoConfigureMockMvcpublic class TestSpringBootTestController { @Autowired private MockMvc mvc; /** * 模擬的 */ @MockBean private UserService userService; @Test public void testGetById() throws Exception { Long userId = 55L; //模擬實現 given(this。userService。findById(userId)) 。willReturn(new User(55L, “MockBean”, 55, “MockBean@qq。com”)); this。mvc。perform(org。springframework。test。web。servlet。request。MockMvcRequestBuilders。get(“/user/” + userId)。accept(MediaType。APPLICATION_JSON))。andExpect(status()。isOk()); }}複製程式碼
方法3。@WebMvcTest+@MockBean
@SpringBootTest 註解不能和 @WebMvcTest 註解同時使用
@WebMvcTest(UserController。class) 該註解將初始化測試 UserController 所必需的 Spring MVC 基礎設施,即是相關bean,不是全部的bean都載入,如不寫則Spring Boot 將在應用程式上下文中包含所有控制器。
@RunWith(SpringRunner。class)@WebMvcTest(UserController。class)public class TestWebMvcTestController { @Autowired private MockMvc mvc; /** * 模擬的 */ @MockBean private UserService userService; @Test public void testGetById() throws Exception { Long userId = 55L; //模擬實現 given(this。userService。findById(userId)) 。willReturn(new User(55L, “MockBean”, 55, “TestWebMvcTestController@qq。com”)); this。mvc。perform(get(“/user/” + userId)。accept(MediaType。APPLICATION_JSON))。andExpect(status()。isOk()); }}
連結:https://juejin。cn/post/7036539195858354213
推薦文章
- 至今都讓你回味無窮的電視劇有哪些?每部都看了一遍又一遍
《香蜜》的熱播,讓劇中的三位主演人氣爆棚,劇火人紅自然是部讓人回味無窮的好劇,小編是看了好多遍的,不知道你追了多少遍...
- 周杰倫發新歌!娛樂圈當今造星與以往偶像的差距在哪?
央視曾報道偶像明星的流量造假現象周杰倫和蔡徐坤的超話之爭的根源其實是兩個代際粉絲相互之間對對方追星/造星模式的不瞭解或者不認可而造成的,後者的粉絲不解前者沒有粉絲去製造流量(相當於沒有熱度),他的演唱會門票卻仍一票難求,而前者的粉絲也厭倦後...
- 長樂:創新數字化管理手段 提升社群治理水平
據悉,智慧(東湖)社群平臺採用雲計算、5G、物聯網、大資料、工作流引擎等眾多前沿技術建設而成,將社群相關的人、事、物進行數字化,並對相關數字資訊進行收集、加工、分發、展示...