SpringBoot使用Junit4單元測試


SpringBoot2.0筆記

 

本篇介紹Springboot單元測試的一些基本操作,有人說一個合格的程序員必須熟練使用單元測試,接下來我們一起在Springboot項目中整合Junit4單元測試。

本文使用idea工具構建Springboot2.0+SpringMvc+Thymeleaf+SpringDataJPA+MySql項目

GitHub地址:https://github.com/jwam/springbootJunit4.git

一、IDEA下載並安裝Junit插件

點擊file-settings,如圖按照順序操作即可,我這里已經安裝過了所以最后一步不會顯示install按鈕。

 二、引入關鍵依賴,完整pom文末給出


   
   
  
  
          
  1. <dependency>
  2. <groupId>org.springframework.boot </groupId>
  3. <artifactId>spring-boot-starter-test </artifactId>
  4. <scope>test </scope>
  5. </dependency>
  6. <dependency>
  7. <groupId>junit </groupId>
  8. <artifactId>junit </artifactId>
  9. <version>4.12 </version>
  10. <!--<scope>test</scope>-->
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework </groupId>
  14. <artifactId>spring-test </artifactId>
  15. <version>5.0.4.RELEASE </version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.springframework.boot </groupId>
  19. <artifactId>spring-boot-test </artifactId>
  20. <version>2.0.0.RELEASE </version>
  21. </dependency>

三、新建UserController.java作為被測試類


   
   
  
  
          
  1. package com.springboot.demo.controller;
  2. import com.springboot.demo.base.controller.BaseController;
  3. import com.springboot.demo.base.utils.StateParameter;
  4. import com.springboot.demo.entity.User;
  5. import com.springboot.demo.service.UserService;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.stereotype.Controller;
  8. import org.springframework.ui.ModelMap;
  9. import org.springframework.util.StringUtils;
  10. import org.springframework.web.bind.annotation.RequestMapping;
  11. import org.springframework.web.bind.annotation.RequestMethod;
  12. import org.springframework.web.bind.annotation.ResponseBody;
  13. import javax.servlet.http.HttpServletRequest;
  14. import java.util.Date;
  15. import java.util.List;
  16. /**
  17. * @ClassName: UserController
  18. * @Auther: zhangyingqi
  19. * @Date: 2018/8/27 17:30
  20. * @Description:
  21. */
  22. @Controller
  23. @RequestMapping(value= "/user")
  24. public class UserController extends BaseController{
  25. @Autowired
  26. UserService userService;
  27. /**
  28. * @auther: zhangyingqi
  29. * @date: 17:37 2018/8/27
  30. * @param: [request, user]
  31. * @return: org.springframework.ui.ModelMap
  32. * @Description: 用戶保存&更新
  33. */
  34. @RequestMapping(value= "/add", method = RequestMethod.POST)
  35. @ResponseBody
  36. public ModelMap add(User user){
  37. try {
  38. if(StringUtils.isEmpty(user.getId())){
  39. user.setId(getUuid());
  40. } else{
  41. user.setUpdateDate( new Date());
  42. }
  43. userService.save(user);
  44. logger.info( "保存成功");
  45. return getModelMap(StateParameter.SUCCESS, user, "保存成功");
  46. } catch (Exception e) {
  47. e.printStackTrace();
  48. return getModelMap(StateParameter.FAULT, null, "保存失敗");
  49. }
  50. }
  51. /**
  52. * @auther: zhangyingqi
  53. * @date: 17:47 2018/8/27
  54. * @param: [id]
  55. * @return: org.springframework.ui.ModelMap
  56. * @Description: 刪除用戶
  57. */
  58. @RequestMapping(value= "/delete", method = RequestMethod.GET)
  59. @ResponseBody
  60. public ModelMap delete(String id){
  61. try {
  62. User user = userService.findById(id);
  63. if(user== null){
  64. return getModelMap(StateParameter.FAULT, user, "找不到該用戶");
  65. }
  66. userService.delete(user);
  67. logger.info( "刪除成功");
  68. return getModelMap(StateParameter.SUCCESS, null, "刪除成功");
  69. } catch (Exception e) {
  70. e.printStackTrace();
  71. return getModelMap(StateParameter.FAULT, null, "刪除失敗");
  72. }
  73. }
  74. /**
  75. * @auther: zhangyingqi
  76. * @date: 17:47 2018/8/27
  77. * @param: [request]
  78. * @return: java.lang.String
  79. * @Description: 查詢用戶列表
  80. */
  81. @RequestMapping(value= "/list")
  82. public String view(HttpServletRequest request){
  83. List<User> list = userService.findAll();
  84. request.setAttribute( "list", list);
  85. logger.info( "返回列表頁面");
  86. return "/demoPage/listPage";
  87. }
  88. }

UserController類中用到的其他依賴都可以去我文章開始提供的GitHub地址下載,其實看過我之前文章的人應該都知道,最簡單的辦法就是直接下載demo了,當然你也可以自己編寫一個controller類,在本篇中並沒有特別要求。

當然不能少了實體類User.java,父類前幾篇文章我都有寫過,demo里也有,節省文本這里不再給出。


   
   
  
  
          
  1. package com.springboot.demo.entity;
  2. import lombok.Data;
  3. import javax.persistence.Column;
  4. import javax.persistence.Entity;
  5. import javax.persistence.Table;
  6. /**
  7. * @ClassName: User
  8. * @Auther: zhangyingqi
  9. * @Date: 2018/8/27 17:17
  10. * @Description:
  11. */
  12. @Entity
  13. @Table(name = "user")
  14. @Data
  15. public class User extends BaseEntity{
  16. @Column(name = "name", length = 100)
  17. private String name;
  18. @Column(name = "age")
  19. private int age;
  20. }

另外還需要list方法返回的實際頁面,在項目template下demoPage下新建listPage.html


   
   
  
  
          
  1. <!DOCTYPE html>
  2. <html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>用戶列表 </title>
  6. </head>
  7. <body>
  8. <div>
  9. <table>
  10. <thead>
  11. <tr>
  12. <th>用戶名稱 </th>
  13. <th>年齡 </th>
  14. <th>創建時間 </th>
  15. </tr>
  16. </thead>
  17. <tbody>
  18. <tr th:if="${list !=null}" th:each="item : ${list}">
  19. <td th:text="${item.name}"> </td>
  20. <td th:text="${item.age}"> </td>
  21. <td th:text="${#dates.format(item.create_date, 'yyyy-MM-dd')}"> </td>
  22. </tr>
  23. </tbody>
  24. </table>
  25. </div>
  26. </body>
  27. </html>

四、生成單元測試類

在UserController中按住alt+insert鍵,如圖選擇將自動生成測試類。

 這時Junit工具將自動生成一個test目錄,在同路徑下生成同類名+Test組合名稱UserControllerTest.java類,這就是自動生成的測試類。

 我們改造這個測試類的內容

首先在類名上加入注解@RunWith和@SpringBootTest,后者需指定springboot啟動類


   
   
  
  
          
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = DemoApplication.class)
  3. public class UserControllerTest {
  4. }

然后引入MockMvc對象及WebApplicationContext上下文,如果涉及業務的測試內容還需引入其他依賴,@Before表示在測試方法執行之前執行會該方法,所以我們在這里實例化mockmvc對象,這樣后面就可以操作他了。


   
   
  
  
          
  1. @RunWith(SpringRunner.class)
  2. @SpringBootTest(classes = DemoApplication.class)
  3. public class UserControllerTest {
  4. /**
  5. * 模擬mvc測試對象
  6. */
  7. private MockMvc mockMvc;
  8. /**
  9. * web項目上下文
  10. */
  11. @Autowired
  12. private WebApplicationContext webApplicationContext;
  13. /**
  14. * 業務數據接口
  15. */
  16. @Autowired
  17. private UserService userService;
  18. /**
  19. * 所有測試方法執行之前執行該方法
  20. */
  21. @Before
  22. public void before() {
  23. //獲取mockmvc對象實例
  24. mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
  25. }
  26. }

接下來我們編寫測試代碼,首先對UserController中的查詢用戶列表方法進行測試,方法頭部需添加@Test注解,具體方法內容如下,使用MockMvcRequestBuilders模擬get請求,status接收返回狀態,responseString接收返回的內容。Assert.assertEquals

為通用的判斷測試執行結果方法,其中三個參數分別為:不一致時提示信息,預期得到結果,實際得到結果。


   
   
  
  
          
  1. @Test
  2. public void testPage() throws Exception {
  3. MvcResult mvcResult = mockMvc
  4. .perform( // 1
  5. MockMvcRequestBuilders.get( "/user/list") // 2
  6. //.param("name","getList") // 3
  7. )
  8. .andReturn(); // 4
  9. int status = mvcResult.getResponse().getStatus(); // 5
  10. String responseString = mvcResult.getResponse().getContentAsString(); // 6
  11. Assert.assertEquals( "請求錯誤", 200, status); // 7
  12. Assert.assertEquals( "返回結果不一致", "/demoPage/listPage", responseString); // 8
  13. }

 接下來執行這個單元測試模塊,IDEA自動檢測到這是一個測試方法,我們直接點擊方法左邊的啟動按鈕即可,因為我已經執行過並且測試未通過,所以顯示紅色,本來是綠色。

 如果執行成功會提示success,我這里提供的這個測試方法執行后是報失敗的,具體原因是在列表頁面獲取不到實體中的create_date字段

做如下修改,將create_date改為createDate即可,所以我們可以看到,測試頁面時會去渲染方法返回的整個html頁面,如果有語法錯誤將會報錯,測試執行失敗。


   
   
  
  
          
  1. <tbody>
  2. <tr th:if="${list !=null}" th:each="item : ${list}">
  3. <td th:text="${item.name}"> </td>
  4. <td th:text="${item.age}"> </td>
  5. <td th:text="${#dates.format(item.create_date, 'yyyy-MM-dd')}"> </td>
  6. </tr>
  7. </tbody>

再次啟動測試單元測試不再報錯,但是依舊執行失敗,提示“返回結果不一致”,我們點擊結果對比發現返回結果有差異,所以未達到期望,直接返回了不一致時的提示信息,因此我們在測試返回頁面時只需執行Assert.assertEquals("請求錯誤", 200, status); 即可,不必再判斷返回期望。

 注釋掉返回結果預期判斷之后執行測試成功。

 那么返回結果預期判斷怎么用呢,我們看下面的第二個測試刪除用戶方法,param可以添加傳遞的參數,預期結果為刪除成功,我這里模擬了刪除成功后的返回json數據,實際應用中可根據情況設定。

 可以看到后台打印刪除成功,同時單元測試執行通過。

本篇我通過Junit4單元測試對springboot項目的controller類進行測試,掌握基本的單元測試在springboot中整合的使用方法。

下面給出完整的pom包,推薦大家直接下載文首給出的demo,可以直接運行,方便又快捷。


   
   
  
  
          
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0 </modelVersion>
  5. <groupId>com.springboot </groupId>
  6. <artifactId>springbootJunit4 </artifactId>
  7. <version>0.0.1-SNAPSHOT </version>
  8. <packaging>war </packaging>
  9. <name>springbootJunit4 </name>
  10. <description>Demo project for Spring Boot </description>
  11. <parent>
  12. <groupId>org.springframework.boot </groupId>
  13. <artifactId>spring-boot-starter-parent </artifactId>
  14. <version>2.0.4.RELEASE </version>
  15. <relativePath/> <!-- lookup parent from repository -->
  16. </parent>
  17. <properties>
  18. <project.build.sourceEncoding>UTF-8 </project.build.sourceEncoding>
  19. <project.reporting.outputEncoding>UTF-8 </project.reporting.outputEncoding>
  20. <java.version>1.8 </java.version>
  21. </properties>
  22. <dependencies>
  23. <dependency>
  24. <groupId>org.springframework.boot </groupId>
  25. <artifactId>spring-boot-starter-tomcat </artifactId>
  26. <!--<scope>provided</scope>-->
  27. </dependency>
  28. <dependency>
  29. <groupId>org.springframework.boot </groupId>
  30. <artifactId>spring-boot-starter-data-jpa </artifactId>
  31. <exclusions>
  32. <exclusion>
  33. <groupId>org.hibernate </groupId>
  34. <artifactId>hibernate-entitymanager </artifactId>
  35. </exclusion>
  36. <exclusion>
  37. <groupId>org.hibernate </groupId>
  38. <artifactId>hibernate-core </artifactId>
  39. </exclusion>
  40. </exclusions>
  41. </dependency>
  42. <dependency>
  43. <groupId>org.hibernate </groupId>
  44. <artifactId>hibernate-core </artifactId>
  45. <version>5.2.10.Final </version>
  46. </dependency>
  47. <dependency>
  48. <groupId>org.springframework.boot </groupId>
  49. <artifactId>spring-boot-starter-data-redis </artifactId>
  50. </dependency>
  51. <dependency>
  52. <groupId>org.springframework.boot </groupId>
  53. <artifactId>spring-boot-starter-mail </artifactId>
  54. </dependency>
  55. <dependency>
  56. <groupId>org.springframework.boot </groupId>
  57. <artifactId>spring-boot-starter-thymeleaf </artifactId>
  58. </dependency>
  59. <dependency>
  60. <groupId>org.springframework.boot </groupId>
  61. <artifactId>spring-boot-starter-web </artifactId>
  62. </dependency>
  63. <dependency>
  64. <groupId>mysql </groupId>
  65. <artifactId>mysql-connector-java </artifactId>
  66. <scope>runtime </scope>
  67. </dependency>
  68. <dependency>
  69. <groupId>org.projectlombok </groupId>
  70. <artifactId>lombok </artifactId>
  71. <optional>true </optional>
  72. </dependency>
  73. <dependency>
  74. <groupId>org.springframework.boot </groupId>
  75. <artifactId>spring-boot-starter-test </artifactId>
  76. <scope>test </scope>
  77. </dependency>
  78. <dependency>
  79. <groupId>junit </groupId>
  80. <artifactId>junit </artifactId>
  81. <version>4.12 </version>
  82. <!--<scope>test</scope>-->
  83. </dependency>
  84. <dependency>
  85. <groupId>org.springframework </groupId>
  86. <artifactId>spring-test </artifactId>
  87. <version>5.0.4.RELEASE </version>
  88. </dependency>
  89. <dependency>
  90. <groupId>org.springframework.boot </groupId>
  91. <artifactId>spring-boot-test </artifactId>
  92. <version>2.0.0.RELEASE </version>
  93. </dependency>
  94. </dependencies>
  95. <build>
  96. <plugins>
  97. <plugin>
  98. <groupId>org.springframework.boot </groupId>
  99. <artifactId>spring-boot-maven-plugin </artifactId>
  100. </plugin>
  101. </plugins>
  102. </build>
  103. </project>

全文完,2018/8/30

原文地址:https://blog.csdn.net/zhulier1124/article/details/82228831


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM