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

时间:2019-04-16 09:56:03

标签: 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 个答案:

答案 0 :(得分:1)

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

1。安装VMware workstation player

2。运行Linux Ubuntu虚拟机

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

3。在Ubuntu VM上安装Docker

  

$ sudo apt-get install docker.io

4。安装后步骤

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

  

$ sudo groupadd泊坞窗

     

$ sudo usermod -aG docker $ USER

4.2。注销并重新登录

以便重新评估您的组成员身份

4.3。确认您可以在没有sudo的情况下运行docker命令

  

$ docker运行hello-world

5。下载数据库映像

在此示例中为Oracle 11g:

  

$ docker pull wnameless / oracle-xe-11g

6。运行数据库映像

(如果您打算从测试容器连接到Oracle数据库实例,则无需执行此步骤)

  

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

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

7。连接到数据库

使用以下设置:

  

主机名:localhost

     

端口:49161

     

sid:xe

     

服务名称:xe

     

用户名:系统

     

密码:甲骨文

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

8。将Docker配置为可以远程访问

配置Docker守护程序在哪里侦听连接(仅在需要远程访问Docker时才需要,即不需要从来宾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

     

[服务]

     

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守护程序重新加载

然后通过运行以下命令重新启动Docker:

  

systemctl重新启动docker.service

8.3。检查您的Docker守护程序

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

  

systemctl状态docker.service

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

  

sudo netstat -tunlp | grep码头

(您应该会看到类似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环境变量

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

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

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的{​​{1}})

  

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

但是从测试容器启动似乎太慢,以至于最终(大约4分钟后)引发了以下异常:

  

java.sql.SQLRecoverableException:ORA-01033:ORACLE初始化或关闭正在进行中。

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