java - 使用 Docker 和 Testcontainers 进行数据库集成测试

标签 java oracle docker windows-7 testcontainers

经过一番研究后,我认为 Docker 容器非常适合使用 test containers 进行数据库集成测试。 ,因为这只需要一个运行数据库镜像的 Docker 容器来复制要执行测试的数据库模式。该实例可以在每个开发人员的计算机上本地运行,或者更好的是,一个实例可以由多个开发人员共享:如果需要,可以使用以下命令将自动化测试配置为从 Docker 中的同一镜像为每种测试方法启动数据库实例@Rule 注释。

在尝试安装适用于 Windows 7 的 Docker 来使用它时,我不断收到以下错误,该错误似乎与 VirtualBox 有关:

docker Error creating machine: Error in driver during machine creation: Unable to start the VM: VBoxManage.exe startvm default --type headless failed:

Result code: E_FAIL (0x80004005)
Component: MachineWrap
Interface: IMachine

我将分享我如何解决这个问题,以帮助其他可能遇到同样问题的人。

最佳答案

为了解决问题中描述的问题,我按照以下步骤操作:

#1。安装VMware workstation player #

#2。运行Linux Ubuntu虚拟机#

使用 Ubuntu website 中的 iso 文件,在 VMware 播放器上运行 Ubuntu 设备

#3。在 Ubuntu 虚拟机上安装 Docker#

$ sudo apt-get install docker.io

#4。安装后步骤#

###4.1。创建 docker 组并添加您的用户###

$ sudo groupadd docker

$ sudo usermod -aG docker $USER

###4.2。注销并重新登录## 以便重新评估您的群组成员资格

###4.3。验证您是否可以在没有 sudo 的情况下运行 docker 命令###

$ docker run hello-world

#5。下载数据库镜像#

在此示例中为 Oracle 11g:

$ docker pull wnameless/oracle-xe-11g-r2

#6。运行数据库镜像#

(如果您打算从testcontainers连接到Oracle数据库实例,则不需要此步骤)

$ docker run -d -p 49161:1521 wnameless/oracle-xe-11g-r2

有关更多详细信息/选项,请参阅 docker hub :

#7。连接数据库#

使用以下设置:

hostname: localhost

port: 49161

sid: xe

service name: xe

username: system

password: oracle

要从主机连接,请使用虚拟机的 IP 地址而不是 localhost 。运行ifconfig在 guest Ubuntu VM 上获取 IP 地址

#8。配置Docker远程访问#

配置 Docker 守护进程监听连接的位置(仅当需要远程访问 Docker 时才需要,即不是从 guest Ubuntu 系统),因为默认情况下 Docker 守护进程监听 unix 套接字(本地连接)

###8.1。创建配置文件###

创建/etc/systemd/system/docker.service.d/override.conf包含要覆盖默认内容的文件 ( ExecStart=/usr/bin/dockerd -H fd:// ):

# /etc/systemd/system/docker.service.d/override.conf

[Service]

ExecStart=

ExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376

要创建此文件,您可以运行以下 unix 命令:

printf "# /etc/systemd/system/docker.service.d/override.conf\n[Service]\nExecStart=\nExecStart=/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376" > /etc/systemd/system/docker.service.d/override.conf

###8.2。重新启动 Docker###

保存此文件后,通过运行重新加载配置:

systemctl daemon-reload

然后通过运行重新启动 Docker:

systemctl restart docker.service

###8.3。检查你的 Docker 守护进程###

重新启动 docker 服务后,您可以在以下任一输出中看到端口号:

systemctl status docker.service

(您应该看到类似:/usr/bin/dockerd -H fd:// -H tcp://0.0.0.0:2376)

或者

sudo netstat -tunlp | grep dock

(您应该看到类似:tcp6 0 0 :::2376 :::* LISTEN 121686/dockerd)

###8.4。有用的资源###

How do I enable the remote API for dockerd

How to detect a docker daemon port

Configure where the docker daemon listens for connections

#9。设置Docker Host环境变量#

仅当您计划使用 testcontainers API(例如,通过 Junit 测试)从托管 Ubuntu VM 的操作系统(docker dameon 在 ubuntu VM 上运行)远程连接到数据库容器时,才需要执行此步骤

定义环境变量:DOCKER_HOST = tcp://<Ubuntu machine's IP address>:2376 。请注意,主机名是 ubuntu VM 的。如果未定义此环境变量,testcontainers API (OracleContainer oracleContainer = new OracleContainer("wnameless/oracle-xe-11g");) 将期望 Docker 守护进程在本地主机上运行(请参阅下面的代码片段)

#10。使用测试类中的数据库容器#

使用 testcontainer API,Junit 测试可以从 Ubuntu 虚拟机上的 Docker 镜像启动数据库实例,对其执行查询,并最终将其关闭

###Junit 测试类###

package com.xxx.yyy.repository;
 
import static org.junit.Assert.assertEquals;
 
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.time.LocalDateTime;
import java.util.concurrent.TimeoutException;
 
import org.junit.ClassRule;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.api.TestInstance.Lifecycle;
import org.testcontainers.containers.OracleContainer;
 
@TestInstance(Lifecycle.PER_CLASS)
public class MyRepositoryIT {
 
    @ClassRule
    public OracleContainer oracleContainer;
 
    @BeforeAll
    public void setup() throws TimeoutException {
        String dockerHost = System.getenv("DOCKER_HOST");
        System.out.println("dockerHost: @" + dockerHost + "@");
 
        System.out.println("Starting Oracle Container... (" + LocalDateTime.now() + ")");
        oracleContainer = new OracleContainer("wnameless/oracle-xe-11g");
        oracleContainer.start();
        System.out.println("Oracle Container started. (" + LocalDateTime.now() + ")");
 
    }
 
    @AfterAll
    public void tearDown() {
        System.out.println("Stopping Oracle Container... (" + LocalDateTime.now() + ")");
        oracleContainer.stop();
        System.out.println("Oracle Container stopped. (" + LocalDateTime.now() + ")");
    }
 
    @Test
    public void whenSelectQueryExecuted_thenResulstsReturned() throws Exception {
 
        String jdbcUrl = oracleContainer.getJdbcUrl();
        String username = oracleContainer.getUsername();
        String password = oracleContainer.getPassword();
        Connection conn = DriverManager.getConnection(jdbcUrl, username, password);
        ResultSet resultSet = conn.createStatement().executeQuery("SELECT 1 FROM DUAL");
        resultSet.next();
        int result = resultSet.getInt(1);
 
        assertEquals(1, result);
 
    }
 
}

####Maven 依赖项###

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.xxx.yyy</groupId>
    <artifactId>docker-testcontainers</artifactId>
    <version>0.0.1-SNAPSHOT</version>
 
    <properties>
        <java.version>1.8</java.version>
        <spring.version>5.1.3.RELEASE</spring.version>
        <testcontainers.version>1.10.2</testcontainers.version>
        <junit-engine.version>5.3.2</junit-engine.version>
        <junit-launcher.version>1.3.2</junit-launcher.version>
        <maven-compiler-plugin.version>3.7.0</maven-compiler-plugin.version>
    </properties>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven-compiler-plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>testcontainers</artifactId>
            <version>${testcontainers.version}</version>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>oracle-xe</artifactId>
            <version>${testcontainers.version}</version>
        </dependency>
        <dependency>
            <groupId>com.oracle</groupId>
            <artifactId>ojdbc6</artifactId>
            <version>12.1.0.2</version>
        </dependency>
 
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit-engine.version}</version>
            <scope>test</scope>
        </dependency>
 
        <dependency>
            <groupId>org.junit.platform</groupId>
            <artifactId>junit-platform-launcher</artifactId>
            <version>${junit-launcher.version}</version>
            <scope>test</scope>
        </dependency>
         
    </dependencies>

#杂记#

###有用的 docker 命令###

  • 列表图像:docker images
  • 列出所有容器:docker ps -a
  • 启动容器:docker start [container id]
  • 列出已启动的容器:docker ps
  • 查看启动容器的日志:docker logs [container id]

###引用资料###

Installing Docker on Ubuntu

Further details about Post-install steps

Using an Oracle image within Docker

Database Testing With TestContainers

###关于 Oracle 12c 镜像###

我尝试过 Oracle 12c 镜像( sath89/oracle-12c 来自: https://hub.docker.com/r/sath89/oracle-12c )

$ docker run -d -p 8080:8080 -p 1521:1521 --name oracle-db-12c sath89/oracle-12c

但是从 testcontainers 启动似乎太慢了,最终(大约 4 分钟后)抛出以下异常:

java.sql.SQLRecoverableException: ORA-01033: ORACLE initialization or shutdown in progress.

如果 12c 镜像是从 docker 主机本身(即 Ubuntu)启动的,则它确实启动成功。

关于java - 使用 Docker 和 Testcontainers 进行数据库集成测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55705417/

相关文章:

java - SimpleDateFormat 中的大写字母

docker - 以非 super 用户身份在docker ubuntu容器中使用 super 用户运行sshd

amazon-web-services - 更新 AWS ECS 服务任务的最佳实践

amazon-web-services - 将 s3 存储桶添加为 docker 卷

java - Hibernate: ORA-01756: 带引号的字符串未正确终止

sql解析器(改变解析方式)

java - 了解位 vector 在查找字符串中的唯一字符时的用法

java - 更改后 JLabel 图标不显示

java - 如果 Json 属性不存在于 java 的构造函数中,则忽略 Json 属性

oracle - 如何在 JSON_ARRAYAGG 中返回不同的值