Spring、Spring Boot和TestNG測試指南 – 整合測試中用Docker建立資料庫

chanjarster發表於2019-01-19

原文地址

測試關係型資料庫一篇裡我們使用的是H2資料庫,這是為了讓你免去你去安裝/配置一個資料庫的工作,能夠儘快的瞭解到整合測試的過程。

在文章裡也說了:

在真實的開發環境中,整合測試用資料庫應該和最終的生產資料庫保持一致

那麼很容易就能想到兩種解決方案:

  1. 開發團隊使用共用同一個資料庫。這樣做的問題在於:當有多個整合測試同時在跑時,會產生錯誤的測試結果。
  2. 每個人使用自己的資料庫。這樣做的問題在於讓開發人員維護MySQL資料庫挺麻煩的。

那麼做到能否這樣呢?

  1. 測試啟動前,建立一個MySQL資料庫
  2. 測試過程中連線到這個資料庫
  3. 測試結束後,刪除這個MySQL資料庫

So, Docker comes to the rescue。

我們還是會以測試關係型資料庫裡的FooRepositoryImpl來做整合測試(程式碼在這裡)。下面來講解具體步驟:

安裝Docker

請查閱官方文件。並且掌握Docker的基本概念。

配置fabric8 docker-maven-plugin

farbic8 docker-maven-plugin顧名思義就是一個能夠使用docker的maven plugin。它主要功能有二:

  1. 建立Docker image
  2. 啟動Docker container

我們這裡使用啟動Docker container的功能。

大致配置如下

 <plugin>
   <groupId>io.fabric8</groupId>
   <artifactId>docker-maven-plugin</artifactId>
   <version>0.28.0</version>

   <configuration>
     <images>
       <image>
         <!-- 使用mysql:8 docker image -->
         <name>mysql:8</name>
         <!-- 定義docker run mysql:8 時的引數 -->
         <run>
           <ports>
             <!-- host port到container port的對映
             這裡隨機選擇一個host port,並將值存到property docker-mysql.port裡 -->
             <port>docker-mysql.port:3306</port>
           </ports>
           <!-- 啟動時給的環境變數,參閱文件:https://hub.docker.com/_/mysql -->
           <env>
             <MYSQL_ROOT_PASSWORD>123456</MYSQL_ROOT_PASSWORD>
             <MYSQL_DATABASE>test</MYSQL_DATABASE>
             <MYSQL_USER>foo</MYSQL_USER>
             <MYSQL_PASSWORD>bar</MYSQL_PASSWORD>
           </env>
           <!-- 設定判定container啟動成功的的條件及timeout -->
           <wait>
             <!-- 如果container打出了這行日誌,則說明容器啟動成功 -->
             <log>MySQL init process done. Ready for start up.</log>
             <time>120000</time>
           </wait>
         </run>
       </image>
     </images>
   </configuration>

   <executions>
     <execution>
       <!-- 在整合測試開始前啟動容器 -->
       <id>start</id>
       <phase>pre-integration-test</phase>
       <goals>
         <goal>start</goal>
       </goals>
     </execution>
     <execution>
       <!-- 在整合測試結束後停止並刪除容器 -->
       <id>stop</id>
       <phase>post-integration-test</phase>
       <goals>
         <goal>stop</goal>
       </goals>
     </execution>
   </executions>
 </plugin>

配置maven-failsafe-plugin

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-failsafe-plugin</artifactId>
  <executions>
    <execution>
      <id>integration-test</id>
      <goals>
        <goal>integration-test</goal>
      </goals>
    </execution>
    <execution>
      <id>verify</id>
      <goals>
        <goal>verify</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <!-- 我們被測的是一個Spring Boot專案,因此可以通過System Properties把MySQL container的相關資訊傳遞給程式
    詳見文件:https://docs.spring.io/spring-boot/docs/1.5.4.RELEASE/reference/html/boot-features-external-config.html
    -->
    <systemPropertyVariables>
      <spring.datasource.url>jdbc:mysql://localhost:${docker-mysql.port}/test</spring.datasource.url>
      <spring.datasource.username>foo</spring.datasource.username>
      <spring.datasource.password>bar</spring.datasource.password>
    </systemPropertyVariables>
  </configuration>
</plugin>

執行

三種常見用法:

  • mvn clean integration-test,會啟動docker container、執行整合測試。這個很有用,如果整合測試失敗,那麼你還可以連線到MySQL資料庫檢視情況。
  • mvn clean verify,會執行mvn integration-test、刪除docker container。
  • mvn clean install,會執mvn verify,並將包安裝到本地maven 倉庫。

下面是mvn clean verify的日誌:

...
[INFO] --- docker-maven-plugin:0.28.0:start (start) @ spring-test-examples-rdbs-docker ---
[INFO] DOCKER> [mysql:8]: Start container f683aadfe8ba
[INFO] DOCKER> Pattern `MySQL init process done. Ready for start up.` matched for container f683aadfe8ba
[INFO] DOCKER> [mysql:8]: Waited on log out `MySQL init process done. Ready for start up.` 13717 ms
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.1:integration-test (integration-test) @ spring-test-examples-rdbs-docker ---
[INFO]
[INFO] -------------------------------------------------------
[INFO]  T E S T S
[INFO] -------------------------------------------------------
...
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- docker-maven-plugin:0.28.0:stop (stop) @ spring-test-examples-rdbs-docker ---
[INFO] DOCKER> [mysql:8]: Stop and removed container f683aadfe8ba after 0 ms
[INFO]
[INFO] --- maven-failsafe-plugin:2.22.1:verify (verify) @ spring-test-examples-rdbs-docker ---
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
...

可以看到fabric8 dmp在整合測試前後start和stop容器的相關日誌,且測試成功。

如何找到MySQL的埠開在哪一個呢?執行docker ps檢視埠(注意下面的0.0.0.0:32798->3306/tcp):

CONTAINER ID  IMAGE     COMMAND  CREATED  STATUS    PORTS                                NAMES
a1f4b51d7c75  mysql:8   ...      ...      Up 19...  33060/tcp, 0.0.0.0:32798->3306/tcp   mysql-1

參考文件

相關文章