为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

POPMUISE 2023-09-20 14:58:15
我使用 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();    }}这就是我创建 Docker 镜像的方式:FROM openjdk:8-jreADD build/distributions/MyPOP3Server.tar . #This is where I have packed all the needed files to. It gets unpacked by Docker.#EXPOSE 24999 #I tried both with and without this exposeWORKDIR /MyPOP3Server/binENTRYPOINT ["sh","MyPOP3Server"] #Executes the shell script which runs java with my jar这是在 Server Jar 内运行的代码的简化版本:MyPOP3Server server = new MyPOP3Server();server.listenToPort(24999);请告诉我我错过了什么。这里有什么问题吗?谢谢并致以亲切的问候。
查看完整描述

4 回答

?
RISEBY

TA贡献1856条经验 获得超5个赞

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

正如已经建议的:

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

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

此外,我希望以下事情能够有所作为。在断点处暂停时:

  • docker ps -a在终端中运行

  • 首先,检查您的容器是否正在运行并且尚未退出。如果它已退出,请从终端查看容器的日志。

  • 其次,检查输出中的端口映射docker ps。您应该看到类似的内容0.0.0.0:32768->24999/tcp(尽管第一个端口号是随机的)。

  • 在您的 IDE 中进行评估container.getFirstMappedPort()并检查您返回的端口号是否与随机公开的端口相同。除非您在本地计算机上安装了非常不寻常的 Docker,否则应该可以通过localhost:+ 此端口访问此容器。

  • 如果您已经走到这一步,那么容器或客户端代码可能有问题。nc您可以尝试将不同的客户端连接到正在运行的容器 -如果您手边没有另一个 POP3 客户端,甚至类似的操作也会有所帮助。

另一件可以尝试的事情是手动运行容器,只是为了减少发生的间接数量。您给出的 Testcontainers 代码片段相当于:

docker run -p 24999 immerfroehlich/emailfilter:latest

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


查看完整回答
反对 回复 2023-09-20
?
慕妹3242003

TA贡献1824条经验 获得超6个赞

尝试添加 http 检查。

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

您的容器可能已启动,但您尝试在服务器初始化之前进行连接。

另外,注册一个日志附加程序以查看容器内服务器的运行情况。

 .withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(
              DockerPop3AutocryptKeyProvidingAndReceivingTest.class)))


查看完整回答
反对 回复 2023-09-20
?
ABOUTYOU

TA贡献1812条经验 获得超5个赞

这引导我找到解决方案。这是缺少 WaitStrategy 和端口映射问题的结合。


这是我所做的:1)在 MyPop3Server.listenToPort(String port) 方法中,我添加了一个 System.out.println:


public class MyPop3Server {

  public void listenToPort(String port) {

     //simplified: do initialization and listenToPort

     System.out.println("Awaiting Connection...");

  }

}

在我的测试中,我添加了一个 LogMessageWaitStrategy 来侦听“等待连接”


GenericContainer container = new GenericContainer<>("immerfroehlich/emailfilter:latest")

   .waitingFor(Wait.forLogMessage("Awaiting Connection.*", 1))

   .withExposedPorts(24999);

2)我从container.getFirstMappedPort()切换到


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();

    }

}


查看完整回答
反对 回复 2023-09-20
?
慕容3067478

TA贡献1773条经验 获得超3个赞

试试container.getMappedPort(24999)getFirstMappedPort。可能您的 docker 映像公开了几个端口。



查看完整回答
反对 回复 2023-09-20
  • 4 回答
  • 0 关注
  • 72 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信