成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Java如何優雅地實現單元測試與集成測試

開發 后端
在日常的開發過程中,為了保證代碼質量,有追求的程序員一般都會對自己編寫的代碼進行充分的測試,這種測試不僅僅是體現在對正常功能的簡單接口調用,而是要根據代碼中的各種邏輯分支,進行盡可能多的覆蓋性單元測試以及主要邏輯的集成測試。

[[332514]]

本文轉載自微信公眾號「 無敵碼農」,作者 無敵碼農。轉載本文請聯系 無敵碼農公眾號。

在日常的開發過程中,為了保證代碼質量,有追求的程序員一般都會對自己編寫的代碼進行充分的測試,這種測試不僅僅是體現在對正常功能的簡單接口調用,而是要根據代碼中的各種邏輯分支,進行盡可能多的覆蓋性單元測試以及主要邏輯的集成測試。

上面說到的測試對于程序員來說,絕不僅僅只是依賴于Postman之類的網絡工具,而要以編寫獨立的單元/集成測試代碼的方式來實現,具體來說在Java中就是要基于JUnit、Mocktio之類的測試框架編寫相應的UT及IT代碼,并在這個過程中提前發現軟件Bug、重新審視所寫代碼并進行優化。

實話說編寫測試代碼對提高軟件質量,及自身編程水平來說都是一種非常有用的手段。但在工作中,并不是所有人都能正確地掌握單元測試和集成測試代碼的寫法和組織形式。以Maven工程代碼為例,很多人會把單元測試和集成測試代碼弄混,這樣導致的后果就是大部分Maven工程代碼:"mvn test"幾乎很難跑通。

而本文想要表達的內容就是如何在Maven工程中有效的區分和組織單元測試、集成測試代碼使得它們互不干擾,并具體演示它們的寫法。

Maven測試代碼結構的組織

 

我們知道在Maven工程結構中“src/test”目錄是專門用于存放測試代碼的,但令人痛苦的是Maven的標準目錄結構只定義了這樣一個測試目錄,也就是說它本身是無法單獨區分單元測試代碼和集成測試代碼的,這也是為什么很多人會把UT和IT代碼同時寫到"src/test"目錄而導致“mvn test”難以跑過的原因。

那么有什么辦法可以友好地解決這個問題呢?在接下來的內容中我們以Maven構建Spring Boot項目為例來具體演示下在Maven中如何友好地分離UT及IT,具體步驟如下:

1)、首先我們創建一個基于Maven構建的Spring Boot項目,代碼結構如下圖所示:

 

如上圖所示,在規劃的目錄結構中我們將IT的代碼目錄及資源文件目錄單獨分離在“src/integration-test”目錄下,默認的“src/test”目錄還是作為存放UT代碼的目錄,而Maven在構建的過程中默認只運行UT代碼。這樣即便IT代碼由于網絡、環境等原因無法正常執行,但也不至于影響到UT代碼的運行。

2)、創建區分UT、IT代碼的Maven Profiles文件

默認情況下Maven是無法主動識別“src/test”目錄之外的測試代碼的,所以當我們將IT代碼抽象到"src/integration-test"目錄之后,需要通過編寫Maven Profiles文件來進行區分,具體示意圖如下:

 

如上圖所示,我們可以在與“src”目錄平行創建一個“profiles”的目錄,其中分別用“dev”、“integration-test”目錄中的config.properties文件來進行區分,其中dev目錄下的config.properties文件的內容為:

  1. profile=dev 

而integration-test目錄中的config.properties文件則為:

  1. profile=integration-test

3)、通過pom.xml文件配置上述profiles文件生效規則

為了使得這些profiles文件生效,我們還需要在pom.xml文件中進行相應的配置。具體如下:

  1. <!--定義關于區分集成測試及單元測試代碼的profiles--> 
  2. <profiles> 
  3.     <!-- The Configuration of the development profile --> 
  4.     <profile> 
  5.         <id>dev</id> 
  6.         <activation> 
  7.             <activeByDefault>true</activeByDefault> 
  8.         </activation> 
  9.         <properties> 
  10.             <build.profile.id>dev</build.profile.id> 
  11.             <!--Only unit tests are run when the development profile is active--> 
  12.             <skip.integration.tests>true</skip.integration.tests> 
  13.             <skip.unit.tests>false</skip.unit.tests> 
  14.         </properties> 
  15.     </profile> 
  16.     <!-- The Configuration of the integration-test profile --> 
  17.     <profile> 
  18.         <id>integration-test</id> 
  19.         <properties> 
  20.             <build.profile.id>integration-test</build.profile.id> 
  21.             <!--Only integration tests are run when the integration-test profile is active--> 
  22.             <skip.integration.tests>false</skip.integration.tests> 
  23.             <skip.unit.tests>true</skip.unit.tests> 
  24.         </properties> 
  25.     </profile> 
  26. </profiles> 

上述內容先定義了區分dev及integration-test環境的的profile信息,接下來在build標簽中定義資源信息及相關plugin,具體如下:

  1. <build> 
  2.     <finalName>${project.artifactId}</finalName> 
  3.     <!--步驟1:單元測試代碼、集成測試代碼分離--> 
  4.     <filters> 
  5.         <filter>profiles/${build.profile.id}/config.properties</filter> 
  6.     </filters> 
  7.     <resources> 
  8.         <resource> 
  9.             <filtering>false</filtering> 
  10.             <directory>src/main/java</directory> 
  11.             <includes> 
  12.                 <include>**/*.properties</include> 
  13.                 <include>**/*.xml</include> 
  14.                 <include>**/*.tld</include> 
  15.                 <include>**/*.yml</include> 
  16.             </includes> 
  17.         </resource> 
  18.         <!--步驟2:通過Profile區分Maven集成測試代碼、單元測試代碼目錄--> 
  19.         <resource> 
  20.             <filtering>true</filtering> 
  21.             <directory>src/main/resources</directory> 
  22.             <includes> 
  23.                 <include>**/*.properties</include> 
  24.                 <include>**/*.xml</include> 
  25.                 <include>**/*.tld</include> 
  26.                 <include>**/*.yml</include> 
  27.                 <include>**/*.sh</include> 
  28.             </includes> 
  29.         </resource> 
  30.     </resources> 
  31.     <plugins> 
  32.         <plugin> 
  33.             <groupId>org.springframework.boot</groupId> 
  34.             <artifactId>spring-boot-maven-plugin</artifactId> 
  35.         </plugin> 
  36.         <!-- 步驟三:將源目錄和資源目錄添加到構建中 --> 
  37.         <plugin> 
  38.             <groupId>org.codehaus.mojo</groupId> 
  39.             <artifactId>build-helper-maven-plugin</artifactId> 
  40.             <version>3.1.0</version> 
  41.             <executions> 
  42.                 <!-- Add a new source directory to our build --> 
  43.                 <execution> 
  44.                     <id>add-integration-test-sources</id> 
  45.                     <phase>generate-test-sources</phase> 
  46.                     <goals> 
  47.                         <goal>add-test-source</goal> 
  48.                     </goals> 
  49.                     <configuration> 
  50.                         <!-- Configures the source directory of our integration tests --> 
  51.                         <sources> 
  52.                             <source>src/integration-test/java</source> 
  53.                         </sources> 
  54.                     </configuration> 
  55.                 </execution> 
  56.                 <!-- Add a new resource directory to our build --> 
  57.                 <execution> 
  58.                     <id>add-integration-test-resources</id> 
  59.                     <phase>generate-test-resources</phase> 
  60.                     <goals> 
  61.                         <goal>add-test-resource</goal> 
  62.                     </goals> 
  63.                     <configuration> 
  64.                         <!-- Configures the resource directory of our integration tests --> 
  65.                         <resources> 
  66.                             <resource> 
  67.                                 <filtering>true</filtering> 
  68.                                 <directory>src/integration-test/resources</directory> 
  69.                                 <includes> 
  70.                                     <include>**/*.properties</include> 
  71.                                 </includes> 
  72.                             </resource> 
  73.                         </resources> 
  74.                     </configuration> 
  75.                 </execution> 
  76.             </executions> 
  77.         </plugin> 
  78.         <!--步驟四:Runs unit tests --> 
  79.         <plugin> 
  80.             <groupId>org.apache.maven.plugins</groupId> 
  81.             <artifactId>maven-surefire-plugin</artifactId> 
  82.             <version>2.18</version> 
  83.             <configuration> 
  84.                 <!-- Skips unit tests if the value of skip.unit.tests property is true --> 
  85.                 <skipTests>${skip.unit.tests}</skipTests> 
  86.                 <!-- Excludes integration tests when unit tests are run --> 
  87.                 <excludes> 
  88.                     <exclude>**/IT*.java</exclude> 
  89.                 </excludes> 
  90.             </configuration> 
  91.         </plugin> 
  92.         <!--步驟五:Runs integration tests --> 
  93.         <plugin> 
  94.             <groupId>org.apache.maven.plugins</groupId> 
  95.             <artifactId>maven-failsafe-plugin</artifactId> 
  96.             <version>2.18</version> 
  97.             <executions> 
  98.                 <execution> 
  99.                     <id>integration-tests</id> 
  100.                     <goals> 
  101.                         <goal>integration-test</goal> 
  102.                         <goal>verify</goal> 
  103.                     </goals> 
  104.                     <configuration> 
  105.                         <skipTests>${skip.integration.tests}</skipTests> 
  106.                     </configuration> 
  107.                 </execution> 
  108.             </executions> 
  109.         </plugin> 
  110.     </plugins> 
  111. </build> 

到這里我們就完成了基于Maven構建的Spring Boot項目的UT及IT代碼目錄的分離配置,此時對UT代碼的執行還是通過默認“mvn test”命令,而集成測試代碼的運行則可以通過如下命令:

  1. mvn clean verify -P integration-test 

單元測試代碼示例

 

通過前面的配置操作就完成了單元測試、集成測試代碼目錄的分離設置。在后續的開發過程中只需要將相應的測試代碼寫在對應的測試目錄即可。接下來我們模擬一段業務邏輯并演示如何編寫其對應的UT代碼。具體如下:

 

如上圖所示,參考MVC三層規范,我們編寫了一個接口邏輯,該接口Controller層接收Http請求后調用Service層進行處理,而Service層處理邏輯時會調用Dao層操作數據庫,并將具體信息插入數據庫。

那么我們編寫單元測試(UT)代碼時,針對的是單獨的某個邏輯單元的測試,而不是從頭到位的整個邏輯,它的運行不應該依賴于任何網絡環境或其他組件,所有依賴的組件或網絡都應該先進行Mock。以單元測試TestServceImpl中的“saveTest”方法為例,其UT代碼編寫如下:

  1. @RunWith(SpringRunner.class) 
  2. @SpringBootTest(classes = TestServiceImpl.class) 
  3. @ActiveProfiles("test"
  4. public class TestServiceImplTest { 
  5.  
  6.     @Autowired 
  7.     TestServiceImpl testServiceImpl; 
  8.  
  9.     @MockBean 
  10.     TestDao testDao; 
  11.  
  12.     @Test 
  13.     public void saveTest() { 
  14.         //調用測試方法 
  15.         testServiceImpl.saveTest("無敵碼農微信公眾號"); 
  16.         //驗證執行測試的邏輯中是否調用過addUser方法 
  17.         verify(testDao).addUser(any()); 
  18.     } 

如上所示UT代碼,我們UT測試的主要對象為TestServiceImpl類,所以可以在@SpringBootTest注解中進行范圍指定。而@ActiveProfiles("test")則表示代碼中所依賴的系統參數,可以從測試資源目錄resouces/application-test.yml文件中獲得。

單元測試的主要目的是驗證單元代碼內的邏輯,對于所依賴的數據庫Dao組件并不是測試的范圍,但是沒有該Dao組件對象,UT代碼在執行的過程中也會報錯,所以一般會通過@MockBean注解進行組件Mock,以此解決UT測試過程中的代碼依賴問題。此時運行“mvn test”命令:

 

單元測試代碼得以正常執行!

集成測試代碼示例

 

在Spring Boot中UT代碼的編寫方式與IT代碼類似,但是其執行范圍是包括了整個上下文環境。我們以模擬從Controller層發起Http接口請求為例,來完整的測試整個接口的邏輯,并最終將數據存入數據庫。具體測試代碼如下:

  1. @RunWith(SpringRunner.class) 
  2. @SpringBootTest 
  3. @ActiveProfiles("test"
  4. public class ITTestControllerTest { 
  5.  
  6.     @Autowired 
  7.     TestController testController; 
  8.  
  9.     @Test 
  10.     public void saveTest() { 
  11.         testController.saveTest("無敵碼農微信公眾號"); 
  12.     } 

可以看到對于集成測試代碼在@SpringBootTest中并沒有指定具體的類,它的默認執行范圍為整個應用的上下文環境。而代碼中的依賴組件由于整個應用上下文都會被啟動,所以依賴上并不會報錯,可以理解為是一個正常啟動的Spring Boot應用。

需要注意的是由于IT代碼的目錄有獨立的資源配置,所以相關的依賴配置,如數據庫等需要在“src/integration-test/resouces/application-test.yml”文件中單獨配置,例如:

  1. spring:
  2.   application: 
  3.     name: springboot-test-demo 
  4.   #數據庫邏輯 
  5.   datasource: 
  6.     url: jdbc:mysql://127.0.0.1:3306/test 
  7.     username: root 
  8.     password: 123456 
  9.     type: com.alibaba.druid.pool.DruidDataSource 
  10.     driver-class-name: com.mysql.jdbc.Driver 
  11.     separator: // 
  12.  
  13. server: 
  14.   port: 8080 

此時運行集成測試命令“mvn clean verify -P integration-test”:

 

 

 

 

可以看到執行IT測試代碼得以正常執行!

后記

 

本文著重介紹了在Java項目中如何編寫單元測試(UT)和集成測試(IT)代碼的工程實踐。在日常編寫代碼的過程中,良好的測試代碼編寫是一種非常好的習慣,一般來說對于UT或IT代碼執行錯誤的工程,要求嚴格的團隊會讓其構建的過程中無法通過,以此來嚴格要求團隊成員。

原文鏈接:https://mp.weixin.qq.com/s/RT-KKT1BskUYEvYAXhms5A

 

責任編輯:武曉燕 來源: 無敵碼農
相關推薦

2017-01-14 23:42:49

單元測試框架軟件測試

2021-01-07 14:06:30

Spring BootJUnit5Java

2021-08-26 11:00:54

Spring BootJUnit5Java

2011-11-30 22:03:49

ibmdwJava

2009-09-01 10:20:06

protected方法單元測試

2011-04-18 13:20:40

單元測試軟件測試

2020-09-30 08:08:15

單元測試應用

2020-08-18 08:10:02

單元測試Java

2017-04-07 13:45:02

PHP單元測試數據庫測試

2023-10-07 08:49:56

測試驅動開發Xunit 框架

2017-02-21 10:30:17

Android單元測試研究與實踐

2017-01-14 23:26:17

單元測試JUnit測試

2017-01-16 12:12:29

單元測試JUnit

2021-03-28 23:03:50

Python程序員編碼

2011-05-16 16:52:09

單元測試徹底測試

2022-03-15 11:55:24

前端單元測試

2021-05-05 11:38:40

TestNGPowerMock單元測試

2017-03-23 16:02:10

Mock技術單元測試

2011-07-04 18:16:42

單元測試

2020-05-07 17:30:49

開發iOS技術
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美成人一区二区 | 免费在线一区二区三区 | 欧美国产日韩在线观看 | 国产精品精品久久久 | 久草网址| 日韩一区二区在线视频 | 亚洲精品视频免费看 | av片毛片| 精品99爱视频在线观看 | 亚洲国产日韩一区 | 伊人久久伊人 | 成人在线中文字幕 | 亚洲看片网站 | 精品一区二区三区在线观看国产 | 久久亚洲综合 | 久久久久久蜜桃一区二区 | 欧美区在线 | 99精品久久久久 | 视频一区二区在线观看 | 国产中文字幕亚洲 | 国产 91 视频 | 成人不卡视频 | 亚洲九九色 | 久久久久无码国产精品一区 | 国产精品久久久久久久 | 亚洲国产成人精品女人久久久 | 草草视频在线观看 | 欧美国产视频 | 免费在线观看h片 | 亚洲男人网 | 成年人视频免费在线观看 | 国产成人午夜精品影院游乐网 | 色呦呦网站 | 蜜桃视频一区二区三区 | 中文字幕免费视频 | 黄色在线免费观看 | 亚洲看片网站 | 91素人| 久久国内精品 | av网站在线免费观看 | 国产不卡视频在线 |