在測試關係型資料庫一篇裡我們使用的是H2資料庫,這是為了讓你免去你去安裝/配置一個資料庫的工作,能夠儘快的瞭解到整合測試的過程。
在文章裡也說了:
在真實的開發環境中,整合測試用資料庫應該和最終的生產資料庫保持一致
那麼很容易就能想到兩種解決方案:
- 開發團隊使用共用同一個資料庫。這樣做的問題在於:當有多個整合測試同時在跑時,會產生錯誤的測試結果。
- 每個人使用自己的資料庫。這樣做的問題在於讓開發人員維護MySQL資料庫挺麻煩的。
那麼做到能否這樣呢?
- 測試啟動前,建立一個MySQL資料庫
- 測試過程中連線到這個資料庫
- 測試結束後,刪除這個MySQL資料庫
So, Docker comes to the rescue。
我們還是會以測試關係型資料庫裡的FooRepositoryImpl
來做整合測試(程式碼在這裡)。下面來講解具體步驟:
安裝Docker
請查閱官方文件。並且掌握Docker的基本概念。
配置fabric8 docker-maven-plugin
farbic8 docker-maven-plugin顧名思義就是一個能夠使用docker的maven plugin。它主要功能有二:
我們這裡使用啟動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