我使用javax.mail实现了POP3服务器和客户端,只是为了尝试与Docker进行集成测试。因此,我基于openjdk:8-jre映像创建了两个Docker映像,并将jars复制到它们并启动了它。根据我的配置(请参见下文),它正在运行。他们正在互相交谈。
但是,由于要进行多个集成测试,因此为每个构建一个映像并启动它们将很繁琐。我也不知道如何自动化结果。 但是后来我偶然发现了TestContainers,这似乎对实现这些测试有很大帮助。
因此,我开始使用POP3服务器映像作为GenericContainer将这些测试移植到TestContainers,并在JUnit测试方法中启动POP3 Client类。我暴露了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-jre
ADD build/distributions/MyPOP3Server.tar . #This is where I have packeded all the needed files to. It gets unpackeded by Docker.
#EXPOSE 24999 #I tried both with and without this expose
WORKDIR /MyPOP3Server/bin
ENTRYPOINT ["sh","MyPOP3Server"] #Executes the shell script wich runs java with my jar
这是在服务器Jar中运行的代码的简化版本:
MyPOP3Server server = new MyPOP3Server();
server.listenToPort(24999);
请告诉我我想念的是什么。怎么了?
谢谢和亲切的问候。
答案 0 :(得分:1)
尝试添加http检查。
new GenericContainer<>("immerfroehlich/emailfilter:latest")
.withExposedPorts(24999)
.waitingFor(new HttpWaitStrategy().forPort(24999)
.withStartupTimeout(Duration.ofMinutes(5)));
容器可能会启动,但是您在服务器初始化之前尝试连接。
此外,注册一个日志附加程序,以查看容器中服务器的运行情况。
.withLogConsumer(new Slf4jLogConsumer(LoggerFactory.getLogger(
DockerPop3AutocryptKeyProvidingAndReceivingTest.class)))
答案 1 :(得分:0)
由于您的邮件服务器和客户端正在容器中运行,我认为您应该连接到端口24999而不是映射的端口
答案 2 :(得分:0)
尝试使用container.getMappedPort(24999)
而不是getFirstMappedPort
。可能您的docker映像暴露了两个端口。
答案 3 :(得分:0)
在其他答案中有一些好的建议;我将通过其他一些技巧来补充这些信息:
正如已经建议的:
绝对添加LogConsumer
,以便您可以看到容器的日志输出-可能在现在或将来会出现一些有用的信息。拥有总是很好。
在启动容器之后,就在启动客户端之前设置断点。
此外,我希望以下事情能有所作为。在断点处暂停时:
docker ps -a
docker ps
输出中的端口映射。您应该看到类似0.0.0.0:32768->24999/tcp
的内容(不过第一个端口号是随机的)。container.getFirstMappedPort()
,并检查返回的端口号是否与随机公开的端口号相同。除非您在本地计算机上安装了非常不寻常的Docker,否则应该可以通过localhost:
+此端口访问此容器。nc
之类的设备也可以提供帮助。另一种尝试是手动运行容器,只是为了减少发生的间接访问量。您提供的Testcontainers代码段等效于:
docker run -p 24999 immerfroehlich/emailfilter:latest
您可能会发现这可以帮助您将问题空间分成较小的部分。
答案 4 :(得分:0)
感谢您的所有帮助。这引导我走向解决方案。这是缺少的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();
}
}
谢谢大家。