如何将测试容器连接到Quarkus DevServices使用的Docker网络
解决方案
你可以通过以下两种方式实现MockServer容器接入Quarkus DevServices的专用网络,适配-Dquarkus.container-image.build=true的场景:
方法1:直接获取Quarkus自动创建的网络,绑定MockServer容器
Quarkus在集成测试启动阶段会将其使用的Docker网络名称通过系统属性quarkus.container-image.network暴露,你可以在测试初始化阶段读取该属性,将MockServer容器接入对应网络即可。你之前使用的Network.SHARED是Testcontainers默认创建的独立网络,和Quarkus为DevServices单独生成的网络不属于同一个,因此无法连通。
调整后的代码如下,无需修改构建参数,同时兼容应用跑在宿主机、容器中两种场景:
@QuarkusIntegrationTest public class JobTest { public static MockServerContainer serverContainer = new MockServerContainer(); // 自定义MockServer在Docker网络中的别名,方便应用容器内部访问 private static final String MOCK_SERVER_ALIAS = "mock-server"; @BeforeAll public static void initMockServer() { // 读取Quarkus自动创建的Docker网络名称,容器模式下该属性才会存在 String quarkusNetwork = System.getProperty("quarkus.container-image.network"); if (quarkusNetwork != null) { // 将MockServer接入Quarkus DevServices专用网络 serverContainer.withNetwork(Network.getNetwork(quarkusNetwork)) .withNetworkAliases(MOCK_SERVER_ALIAS); } // 启动MockServer容器 serverContainer.start(); // 初始化MockServer规则,测试代码跑在宿主机,所以用宿主机映射的端口访问 String json = ... new MockServerClient(serverContainer.getHost(), serverContainer.getServerPort()) .when(request() .withMethod("GET") .withPath(".*")) .respond(response() .withStatusCode(Response.Status.OK.getStatusCode()) .withHeader(CONTENT_TYPE, MediaType.APPLICATION_JSON) .withBody(json)); } @Test @DisplayName("import recipe from website") public void importRecipe() { String recipeUrl; String quarkusNetwork = System.getProperty("quarkus.container-image.network"); if (quarkusNetwork != null) { // 应用跑在容器中时,同一网络下直接用别名+MockServer内部默认端口1080访问 recipeUrl = String.format("http://%s:%d/lasagne.html", MOCK_SERVER_ALIAS, 1080); } else { // 应用跑在宿主机时,用localhost+宿主机映射端口访问 recipeUrl = String.format("http://localhost:%d/lasagne.html", serverContainer.getServerPort()); } // 应用接口URL逻辑不变,Quarkus会自动将容器内应用端口映射到宿主机 var jobUrl = String.format("http://localhost:%s/job", System.getProperty("quarkus.http.port")); RestAssured .given() .body(createJob(recipeUrl)) .contentType(ContentType.JSON) .when() .post(jobUrl) .then() .statusCode(Response.Status.CREATED.getStatusCode()) .header("Location", r -> equalTo(url + "/" + r.path("jobId"))); } @AfterAll public static void stopMockServer() { if (serverContainer.isRunning()) { serverContainer.stop(); } } }
该方案原生适配Quarkus 2.3.0版本,无需引入额外依赖。
方法2:自定义测试资源统一管理容器
如果有多个测试类需要复用MockServer,可以实现QuarkusTestResourceLifecycleManager接口,在Quarkus测试启动的早期阶段初始化MockServer容器,直接绑定到DevServices网络,避免每个测试类重复编写容器初始化逻辑。
内容的提问来源于stack exchange,提问作者54v054r3n
相关产品推荐
相关产品推荐

