Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I connect a test container in Quarkus to the Docker network of DevServices?

In my @QuarkusIntegrationTest I want to use a MockServer testcontainer that simulates the responses to requests from my application. To start the MockServer I use testcontainers. The application uses http://localhost:port, where port is mockserverContainer.getMappedPort (). It all works.

When I test the application with -Dquarkus.container-image.build=true, I get the following problem: Quarkus creates a Docker network and connects the container with the application and the MongoDb test container to this network via the DevServices. I would also like to bring the MockServer test container into this network, but I can't. Network.SHARED that is available in the test is not the network that Quarkus uses for the DevServices. Of course, I can use the host's IP address to access the MockServer from the application that is being tested, which complicates the build scripts because the host's IP address is not that easy to determine in every environment.

Is there any way that the testcontainer can connect to the Docker network used by the Quarkus DevService?

(Quarkus Version 2.3.0)

The following example works with the -Dquarkus.container-image.build=false option, i.e. if the application itself is not running in a container.

@QuarkusIntegrationTest
@Testcontainers
public class JobTest {

    @Container
    public static MockServerContainer serverContainer = new MockServerContainer()

    @BeforeAll
    public static initMockServer() {
      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() {
        // The URL that the application wants to get data from. Is simulated by the MockServer. 
        var recipeUrl = String.format("http://localhost:%d/lasagne.html", serverContainer.getServerPort());
        // The URL of the application that triggered the import function. 
        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")));
    }
}

like image 225
54v054r3n Avatar asked Jan 25 '26 02:01

54v054r3n


1 Answers

As of Quarkus 2.5, you will be able to do something like:

public class CustomResource implements QuarkusTestResourceLifecycleManager, DevServicesContext.ContextAware {

    private Optional<String> containerNetworkId = Optional.empty(); 

    @Override
    public Map<String, String> start() {
        // start a container here using containerNetworkId
        return someMap;
    }

    @Override
    public void stop() {
        // close the container
    }


    @Override
    public void setIntegrationTestContext(DevServicesContext context) {
        containerNetworkId = context.containerNetworkId();
    }
}

and your test would be:

@QuarkusIntegrationTest
@QuarkusTestResource(CustomResource.class)
public class JobTest {
  

   ...


}

See this for more details.

like image 97
geoand Avatar answered Jan 26 '26 19:01

geoand