无法连接到测试容器Neo4J实例?

时间:2020-08-19 20:55:07

标签: docker kotlin neo4j junit5 testcontainers

这是我的测试课:

@Testcontainers
@ReactiveDataNeo4jTest
internal class RepositoryIT {

    @Container
    private val container = KNeo4jContainer.instance

    @Test
    fun `should answer with One`() {
        val boltUrl = container.getBoltUrl()
        GraphDatabase.driver(
                boltUrl,
                AuthTokens.basic("neo4j", "123456"))
                .use { driver ->
                    driver.session().use { session ->
                        val res = session.run("OPTIONAL MATCH(n) RETURN 1 AS value")
                        val one = res.single().get("value").asInt()
                        assertThat(one).isEqualTo(2)
                    }
                }

    }

}

object KNeo4jContainer {

    val instance by lazy {
        startNeo4jContainer()
    }

    private fun startNeo4jContainer(): Neo4jContainer<*> =
            Neo4jContainer<Nothing>("neo4j:4.1.0").apply {
                withEnv("NEO4J_AUTH", "neo4j/123456")
                withExposedPorts(7687)
                withExposedPorts(7473)
                withExposedPorts(7474)
                start()
            }
}

当我检查docker ps -a时,它似乎已经开始

  CONTAINER ID   IMAGE                               COMMAND                  CREATED              STATUS              PORTS                                                                       NAMES                                                     
 -------------- ----------------------------------- ------------------------ -------------------- ------------------- --------------------------------------------------------------------------- ---------------------------------------------------------- 
  102b11fa5c7c   neo4j:4.1.0                         "/sbin/tini -g -- /d…"   About a minute ago   Up About a minute   0.0.0.0:32791->7473/tcp, 0.0.0.0:32790->7474/tcp, 0.0.0.0:32789->7687/tcp   pensive_williams                                          
  92fac72190e0   testcontainersofficial/ryuk:0.3.0   "/app"                   About a minute ago   Up About a minute   0.0.0.0:32788->8080/tcp                                                     testcontainers-ryuk-ecc3bfaf-44ba-482d-ae5f-ddba9a70182f

但是我无法连接到它:

org.neo4j.driver.exceptions.ServiceUnavailableException:无法执行 连接到localhost:7687,确保数据库正在运行,并且 到它的网络连接正常。

我可以通过docker-compose up对以相同配置启动的容器进行测试:

version: "3.1"
services:
  neo4j:
    image:  neo4j:4.1.0
    ports:
      # Http
      - "7474:7474"
      # Https
      - "7473:7473"
      # Bolt
      - "7687:7687"
    environment:
      # initial password reset
      "NEO4J_AUTH": "neo4j/secret"

但是我认为那仅仅是因为在开发测试时不必启动新容器。

我在做什么错了?

修改

在启动代码中将admin passwort设置为null后,已将AuthTokens更改为AuthTokens.none()-仍然没有成功。

修改

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/>
    </parent>
    <!-- groupId, artifactId, version, name and description ommitted -->
    <properties>
        <java.version>11</java.version>
        <kotlin.version>1.3.72</kotlin.version>
        <neo4j.test.port>7687</neo4j.test.port>
        <neo4j.test.auth>neo4j/secret</neo4j.test.auth>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-webflux</artifactId>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-kotlin</artifactId>
        </dependency>
        <dependency>
            <groupId>io.projectreactor.kotlin</groupId>
            <artifactId>reactor-kotlin-extensions</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-reflect</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-stdlib-jdk8</artifactId>
        </dependency>
        <dependency>
            <groupId>org.jetbrains.kotlinx</groupId>
            <artifactId>kotlinx-coroutines-reactor</artifactId>
        </dependency>
        <dependency>
            <groupId>org.neo4j.springframework.data</groupId>
            <artifactId>spring-data-neo4j-rx-spring-boot-starter</artifactId>
            <version>1.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency><dependency>
        <groupId>org.neo4j.springframework.data</groupId>
        <artifactId>spring-data-neo4j-rx-spring-boot-starter</artifactId>
        <version>1.1.1</version>
    </dependency>
        <dependency>
            <groupId>org.neo4j.driver</groupId>
            <artifactId>neo4j-java-driver</artifactId>
            <version>4.1.1</version>
        </dependency>
        <dependency>
            <groupId>org.neo4j.springframework.data</groupId>
            <artifactId>spring-data-neo4j-rx-spring-boot-test-autoconfigure</artifactId>
            <version>1.1.1</version>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.neo4j.test</groupId>
                    <artifactId>neo4j-harness</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>io.projectreactor</groupId>
            <artifactId>reactor-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.4.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-params</artifactId>
            <version>5.4.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.4.2</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>testcontainers</artifactId>
            <version>1.14.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>junit-jupiter</artifactId>
            <version>1.14.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.testcontainers</groupId>
            <artifactId>neo4j</artifactId>
            <version>1.14.3</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
        <testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.jetbrains.kotlin</groupId>
                <artifactId>kotlin-maven-plugin</artifactId>
                <configuration>
                    <args>
                        <arg>-Xjsr305=strict</arg>
                    </args>
                    <compilerPlugins>
                        <plugin>spring</plugin>
                    </compilerPlugins>
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.jetbrains.kotlin</groupId>
                        <artifactId>kotlin-maven-allopen</artifactId>
                        <version>${kotlin.version}</version>
                    </dependency>
                </dependencies>
            </plugin>
            <plugin>
                <groupId>io.fabric8</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.33.0</version>
                <configuration>
                    <images>
                        <image>
                            <name>neo4j:4.1.0</name>
                            <alias>neo4j</alias>
                            <run>
                                <env>
                                    <NEO4J_AUTH>${neo4j.test.auth}</NEO4J_AUTH>
                                </env>
                                <ports>
                                    <port>${neo4j.test.port}:3306</port>
                                </ports>
                                <wait>
                                    <!-- time based waiting is the only option, because TCP-based or log-based polling are not reliable.
                                   see https://github.com/fabric8io/docker-maven-plugin/issues/328
                                   Alternatively we can wait log- or tcp-based and try to connect for a while in the test code -->
                                    <time>8000</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>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-failsafe-plugin</artifactId>
                <version>2.18.1</version>
                <configuration>
                    <includes>
                        <include>**/*IT.*</include>
                    </includes>
                    <systemPropertyVariables>
                        <neo4j.port>${neo4j.test.port}</neo4j.port>
                        <neo4j.auth>${neo4j.test.auth}</neo4j.auth>
                    </systemPropertyVariables>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>integration-test</goal>
                            <goal>verify</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M4</version>
                <configuration>
                    <excludes>
                        <exclude>**/*IT.*</exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

解决方案

 private fun startNeo4jContainer(): Neo4jContainer<*> {
        val container = Neo4jContainer<Nothing>("neo4j:4.1.0").apply {
            withAdminPassword(null)
            start()
        }
        return container
    }

3 个答案:

答案 0 :(得分:1)

考虑使用Neo4jContainer#withAdminPassword来设置密码,而不是设置环境变量。

否则,它将在此处被覆盖: https://github.com/testcontainers/testcontainers-java/blob/6bdbc8ffe257fc879791eb7fddcf3b5ecccdd52d/modules/neo4j/src/main/java/org/testcontainers/containers/Neo4jContainer.java#L118

答案 1 :(得分:0)

之所以会这样,是因为在Windows中,默认的0.0.0.0地址未转换为本地主机。

我无法复制,但是添加以下环境变量应该可以完成工作:

version: "3.1"
services:
  neo4j:
    image:  neo4j:4.1.0
    ports:
      # Http
      - "7474:7474"
      # Https
      - "7473:7473"
      # Bolt
      - "7687:7687"
    environment:
      # initial password reset
      - NEO4J_AUTH=neo4j/secret
      - NEO4J_dbms_connector_https_advertised__address=localhost:7473
      - NEO4J_dbms_connector_http_advertised__address=localhost:7474
      - NEO4J_dbms_connector_bolt_advertised__address=localhost:7687

答案 2 :(得分:0)

这与https://www.testcontainers.org/features/networking/

有点不同

从主持人的角度来看,Testcontainers实际上将此内容公开在 随机的免费端口。这是设计使然,以避免可能发生端口冲突的情况。 在本地运行的软件中或在并行测试运行之间出现。

https://www.testcontainers.org/modules/databases/jdbc/的底部

现在,在测试代码(或合适的设置方法)中,您可以获得 连接到该数据库所需的详细信息:

  • mysql.getJdbcUrl()提供了您的代码可以连接到的JDBC URL
  • mysql.getUsername()提供了您的代码应传递给驱动程序的用户名
  • mysql.getPassword()提供了您的代码应传递给驱动程序的密码