在 Gradle 中设置Testcontainer

在开发现代 Java 应用程序时,测试中需要一些外部服务(例如数据库、消息代理或 Web 服务器)的情况很常见。传统上,这需要手动设置这些服务,这通常容易出错,并且在不同的环境中不易处理。Testcontainers 是一个流行的 Java 库,它允许测试在常用数据库、Selenium Web 浏览器或可以在 Docker 容器中运行的任何其他轻量级、一次性实例中运行。

本指南将指导您完成使用 Gradle 与 Testcontainers 集成的过程,从设置环境到运行测试。

先决条件
 在继续操作之前,请确保您的系统中已安装以下软件: 

  • Java 8 或更高版本:Testcontainers 至少需要 Java 8。
  • Gradle:以下教程基于Gradle作为构建工具。
  • Docker:由于 Testcontainers 使用 Docker 来运行容器,因此您需要在主机上安装并运行 Docker。

Gradle 项目的准备
你还没有设置 Gradle 项目吗?没问题,下面介绍如何设置:

1.创建一个新的Gradle项目:
 gradle init --type java-application

2.项目结构:
   你的项目结构在初始化时应该看起来像这样:

   ├── build.gradle
   ├── settings.gradle
   └── src
       ├── main
       │   └── java
       └── test
└── java

将 Testcontainers 排除在构建之外
现在,您需要在 build.gradle 文件中添加 Testcontainers 的依赖项。

1、添加 Testcontainer 的依赖项 在 build.gradle 文件中添加下一个依赖项。

dependencies {
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.3'
    testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.3'
    testImplementation 'org.testcontainers:junit-jupiter:1.19.0'
    testImplementation 'org.testcontainers:mysql:1.19.0' // Example for MySQL, add other modules as needed
}

test {
    useJUnitPlatform()
}


此设置启用了 JUnit 5 和 Testcontainers。您可以将 MySQL 模块替换为您可能需要的任何其他模块,例如“postgresql”、“redis”等。

2.保证Docker的可用性:
   测试容器需要您的环境中有 Docker。只需通过执行以下命令确保 Docker 正在运行:
   docker --version

如果 Docker 安装正确,此命令将返回 Docker 版本。

使用 Testcontainers 编写简单测试
现在您的项目已配置为使用 Testcontainers,让我们创建一个简单的测试。

1. 在src/test/java中创建一个新的测试类,例如MySQLContainerTest.java

import org.junit.jupiter.api.Test;
import org.testcontainers.containers.MySQLContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
import static org.junit.jupiter.api.Assertions.assertTrue;

   @Testcontainers
   public class MySQLContainerTest {

       @Container
       public MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0.26")
               .withDatabaseName(
"testdb")
               .withUsername(
"test")
.withPassword(
"test");

       @Test
       void testMySQLContainerIsRunning() {
           mysql.start();
           assertTrue(mysql.isRunning());
       }
   }


在此示例中:
   - 我们创建一个“MySQLContainer”,它将使用官方 MySQL 8.0.26 Docker 镜像。
   - 然后,测试将检查包含 MySQL 的容器是否已启动并准备就绪。


2.运行测试:
   现在你可以使用 Gradle 执行测试:

  ./gradlew test

Gradle 将执行测试,Testcontainers 将看到 @Container 注释,透明地为 MySQL 拉取 Docker 镜像,启动容器,执行测试,然后停止容器。

高级配置
Testcontainers 附带了几个您可能觉得有用的高级配置。其中包括以下内容: 

1.重复使用容器:
默认情况下,Testcontainers 会在每次测试结束时启动和停止容器。您可以通过重复使用容器来加快测试速度,方法是在 ~/.testcontainers.properties 中将 testcontainers.reuse.enable 设置为 true。这将启用容器重用。

testcontainers.reuse.enable=true

2. 自定义容器设置
容器的行为可以进一步定制 - 例如,您可能希望公开其他端口或安装卷。具体操作如下:

MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0.26")
           .withExposedPorts(3306)
           .withEnv(
"MYSQL_ROOT_PASSWORD", "rootpass")
           .withFileSystemBind(
"/my/local/path", "/container/path");


   
3.自定义Docker网络:
如果您的测试需要多个容器相互交互,则可以将它们放在同一个 Docker 网络上:

Network network = Network.newNetwork();

MySQLContainer<?> mysql = new MySQLContainer<>("mysql:8.0.26")
        .withNetwork(network)
        .withNetworkAliases(
"mysql");

GenericContainer<?> app = new GenericContainer<>(
"myapp:latest")
 
.withNetwork(network)
           .withEnv(
"DB_HOST", "mysql");