Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Testcontainers-无法连接到公开的端口_Java_Docker_Junit_Dockerfile_Testcontainers - Fatal编程技术网

Java Testcontainers-无法连接到公开的端口

Java Testcontainers-无法连接到公开的端口,java,docker,junit,dockerfile,testcontainers,Java,Docker,Junit,Dockerfile,Testcontainers,我使用javax.mail实现了一个POP3服务器和客户端,只是为了尝试与Docker进行集成测试。因此,我基于openjdk:8-jre映像创建了两个Docker映像,并将我的JAR复制到它们并启动了它。根据我的配置(见下文),它正在工作。他们正在互相交谈 但是,如果您希望进行多个集成测试,那么为每个测试构建一个映像并启动它们将是一件乏味的事情。我也不知道如何自动生成结果。 但后来我偶然发现了TestContainers,这似乎对实现这些测试有很大帮助 因此,我开始使用POP3服务器映像作为G

我使用javax.mail实现了一个POP3服务器和客户端,只是为了尝试与Docker进行集成测试。因此,我基于openjdk:8-jre映像创建了两个Docker映像,并将我的JAR复制到它们并启动了它。根据我的配置(见下文),它正在工作。他们正在互相交谈

但是,如果您希望进行多个集成测试,那么为每个测试构建一个映像并启动它们将是一件乏味的事情。我也不知道如何自动生成结果。 但后来我偶然发现了TestContainers,这似乎对实现这些测试有很大帮助

因此,我开始使用POP3服务器映像作为GenericContainer将这些测试移植到TestContainers,并在JUnit测试方法中启动POP3客户机类。我暴露了我的POP3服务器正在监听的端口24999。但当我尝试连接到服务器时,出现以下错误:

com.sun.mail.util.MailConnectException: Couldn't connect to host, port: localhost, 32782; timeout -1;
  nested exception is:
    java.net.ConnectException: Connection refused
...
TestContainers中可能缺少一些设置。你能帮帮我吗

以下是我正在使用的代码:

public class DockerPop3AutocryptKeyProvidingAndReceivingTest {
    @Test
    public void test() throws InterruptedException {
        GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
                .withExposedPorts(24999);

        container.start();

        String host = container.getContainerIpAddress();
        String port = container.getFirstMappedPort().toString();

        //The following is simplified, but copied from the working jar used in the Docker Client image/container
        MyPOP3Client client = new MyPOP3Client(host, port);
        client.connect();

        container.stop();
    }
}
这是在服务器Jar中运行的代码的简化版本:

MyPOP3Server server = new MyPOP3Server();
server.listenToPort(24999);
请告诉我我错过了什么。这里怎么了


谢谢并致以亲切的问候。

由于您的邮件服务器和客户端正在容器中运行,我认为您应该连接到端口24999,而不是映射端口尝试
容器。getMappedPort(24999)
而不是
getFirstMappedPort
。您的docker映像可能会暴露几个端口。

尝试添加http检查

 new GenericContainer<>("immerfroehlich/emailfilter:latest")
 .withExposedPorts(24999)
 .waitingFor(new HttpWaitStrategy().forPort(24999)
 .withStartupTimeout(Duration.ofMinutes(5)));

其他答案中有一些很好的建议;我将用几个其他提示来补充这些内容:

正如已经建议的那样:

  • 绝对要添加
    LogConsumer
    ,这样您就可以看到容器的日志输出——也许现在或将来会出现一些有用的东西。拥有总是好的

  • 在容器启动后,即启动客户端之前,设置断点

此外,我希望以下几点会有所不同。在断点处暂停时:

  • 在终端中运行
    docker ps-a
  • 首先,检查您的容器是否正在运行且未退出。如果它已退出,请从终端查看容器的日志
  • 其次,检查
    docker ps
    输出中的端口映射。您应该看到类似于
    0.0.0.0:32768->24999/tcp
    (但第一个端口号是随机的)
  • 在IDE中评估container.getFirstMappedPort(),并检查返回的端口号是否与随机公开的端口号相同。除非您在本地计算机上安装了非常不寻常的Docker,否则应该可以通过
    localhost:
    +此端口访问此容器
  • 如果您已经做到这一点,那么很可能是容器或客户机代码出了问题。您可以尝试将不同的客户端连接到正在运行的容器,如果手头没有另一个POP3客户端,甚至可以使用类似的方法
另一种尝试是手动运行容器,以减少发生的间接寻址量。您给出的Testcontainers代码段等效于:

docker run -p 24999 immerfroehlich/emailfilter:latest

您可能会发现,这有助于将问题空间划分为更小的部分。

谢谢您的帮助。这使我找到了解决办法。这是缺少WaitStrategy和端口映射问题的结合

以下是我所做的: 1) 在MyPop3Server.listenToPort(字符串端口)方法中,我添加了System.out.println:

public class MyPop3Server {
  public void listenToPort(String port) {
     //simplified: do initialization and listenToPort
     System.out.println("Awaiting Connection...");
  }
}
在我的测试中,我添加了一个LogMessageWaitStrategy,用于侦听“等待连接”

以下是整个已更改且正在运行的测试代码:

public class DockerPop3AutocryptKeyProvidingAndReceivingTest {
    @Test
    public void test() throws InterruptedException {
        GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
                .waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))
                .withExposedPorts(24999);

        container.start();

        String host = container.getContainerIpAddress();
        String port = container.getMappedPort(24999).toString();

        //The following is simplified, but copied from the working jar used in the Docker Client image/container
        MyPOP3Client client = new MyPOP3Client(host, port);
        client.connect();

        container.stop();
    }
}
公共类Dockerp3AutocryptKeyProvisingandReceivingTest{
@试验
public void test()引发InterruptedException{
GenericContainer=新的GenericContainer(“immerfroehlich/emailfilter:最新”)
.waitingFor(Wait.forLogMessage(“waiting Connection.*”,1))
.具有暴露端口(24999);
container.start();
字符串host=container.getContainerIpAddress();
String port=container.getMappedPort(24999.toString();
//以下内容已简化,但复制自Docker客户端映像/容器中使用的工作jar
MyPOP3Client client=新的MyPOP3Client(主机、端口);
client.connect();
container.stop();
}
}

谢谢大家。

您能否在容器启动后创建一个断点,并检查它以查看映射了哪个端口。无论如何,如果您执行类似于port=container.getMappedPort(24999)的操作,好的,我将更改为port=container.getMappedPort(24999),但它无论如何都不工作。我做了调试,但我不确定在哪里看。container.exposedPorts为[24999];container.portBindings是[]。不,这是我最初做的。我只是想提一下,这样就没有人会问你的服务器是否正常工作了。目前,服务器在容器中运行,客户端在JUnit测试中本地运行。我试过了,但没用。如果你在客户端连接之前设置了一个断点,你能使用telnet或其他邮件客户端连接到映射端口吗?不,它也不起作用。但后来我在命令行上用Docker启动了容器,它也不起作用。然后我读了docker手册中关于网络的内容,我有了一个想法。因此,两个容器可以相互通信,但主机不能与容器通信。手册中说网桥网络是默认网络。它有什么作用?它允许两个容器相互通信(可能更多)。所以我读了关于主机网络的文章。它基本上说在Linux上它和主机在同一个网络上。。。。。。我直接用“docker run-I-t——网络主机immerfroehlich/emailfilter:latest”和tada启动容器,我可以连接到
public class MyPop3Server {
  public void listenToPort(String port) {
     //simplified: do initialization and listenToPort
     System.out.println("Awaiting Connection...");
  }
}
GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
   .waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))
   .withExposedPorts(24999);
container.getMappedPort(24999);
public class DockerPop3AutocryptKeyProvidingAndReceivingTest {
    @Test
    public void test() throws InterruptedException {
        GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")
                .waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))
                .withExposedPorts(24999);

        container.start();

        String host = container.getContainerIpAddress();
        String port = container.getMappedPort(24999).toString();

        //The following is simplified, but copied from the working jar used in the Docker Client image/container
        MyPOP3Client client = new MyPOP3Client(host, port);
        client.connect();

        container.stop();
    }
}