From ea52f8adc349cfd5e8898c242d6620b70de22f50 Mon Sep 17 00:00:00 2001 From: Fabio Burzigotti Date: Tue, 21 Jan 2025 08:41:09 +0100 Subject: [PATCH 1/2] Blog post: Testing on Docker wtth Arquillian Cube --- ...025-01-21-testing-on-docker-with-cube.adoc | 387 ++++++++++++++++++ 1 file changed, 387 insertions(+) create mode 100644 _posts/2025-01-21-testing-on-docker-with-cube.adoc diff --git a/_posts/2025-01-21-testing-on-docker-with-cube.adoc b/_posts/2025-01-21-testing-on-docker-with-cube.adoc new file mode 100644 index 000000000..26845b9b9 --- /dev/null +++ b/_posts/2025-01-21-testing-on-docker-with-cube.adoc @@ -0,0 +1,387 @@ +--- +layout: post +title: Testing WildFly applications on Docker with Arquillian Cube +date: 2025-01-21 +tags: wildfly docker arquillian cube containers +synopsis: Arquillian Cube is an Arquillian extension that provides an easy way to test a WildFly containerized application on Docker +author: fabiobrz +--- + += Testing WildFly applications on Docker with Arquillian Cube + +Recently we resumed the https://github.com/arquillian/arquillian-cube[Arquillian Cube] project as a way to test on +containerized environments, such as Docker, Kubernetes, and OpenShift. +The last (pre)release is https://github.com/arquillian/arquillian-cube/releases/tag/2.0.0.Alpha1[2.0.0.Alpha1], and it +aims at filling the gap with the 1.18.2 release, by running against more recent versions of target environments (again, +Docker, Kubernetes and OpenShift). + +This example provides the guidance to set up an automated integration test for a WildFly application that should be run +on Docker. + +In order to do so, we'll start from the +https://www.wildfly.org/guides/get-started-microservices-on-kubernetes/simple-microservice-part1[WildFly Java Microservice - PART 1: Docker Image] guide, which will be modified to show how to implement a JUnit test that will use an _existing_ Dockerfile +to automate the image build and execution. + +== Use case +The original article uses Maven archetypes to provide the reader with a ready-to-use WildFly application project. +And it works great, definitely! + +But in the last section, the user is instructed on how to build the Docker image, and about testing it manually. +This article is all about this: using Arquillian Cube to automate the image build, and the Docker container setup and +execution, while leveraging annotations and APIs at the test class level, to let the developer focus on the +actual test logic. + +In the following sections we'll see which steps we need to take in order to modify the original example and achieve what above. + +== Step by step changes + +As said, we need to start from the +https://www.wildfly.org/guides/get-started-microservices-on-kubernetes/simple-microservice-part1[WildFly Java Microservice - PART 1: Docker Image] article, so make sure to go through it, then... + +=== Docker `compose` and _Dockerfile_ resources + +Let's start and create a new `docker-build` directory at the project root: + +[source,shell] +---- +mkdir docker-build +---- + +and put the Dockerfile - i.e. the one we created in the original article - inside it. We'll need to change just one +line, i.e. we should replace the path `target/server` with just `server`, we'll see why later on. + +As you can see, we reused the _Dockerfile_ which we created in the original example, which defines how the +image should be built. + +Then we should create a `docker-compose.yml` file at the project root, as well, with the following contents: + +[source,yaml] +---- +version: '2' +services: + wildfly: + build: + context: docker-build + ports: + - "9991:9990" + - "8081:8080" + networks: + - front-tier +networks: + front-tier: +---- + +Here we've defined how the Docker container should run the image created previously. +Specifically, we can see that a container named `wildfly` will be started, building an image as per the _Dockerfile_ +which is in the `docker-build` sub-directory, and exposing the container `8080` and `9990` ports via the host's +`8081` and `9991` ones, respectively. + +That's all about what we need on the Docker side. Arquillian Cube will automate the `docker compose` build that +will use the Dockerfile which was created already to build and run the WildFly application image. + +In the following section we'll modify the project POM to use Arquillian Cube. + +=== Update the example project POM + +First off, let's add the following `properties` to define some required versions: + +[source,xml] +---- + 2.0.0.Alpha1 + 1.8.0.Final + 4.13.2 + 2.0.16 +---- + +Then we need to comment out, or remove, the following declaration of the JUnit 5 BOM off the `dependencyManagement` +section, since Arquillian Cube will use JUnit 4 instrumentation by default: +[source,xml] +---- + + + + + + + + + +---- + +and finally let's add the following dependencies to the `dependencyManagment` section, which are what we need to use +Arquillian Cube: + +[source,xml] +---- + + + org.arquillian.cube + arquillian-cube-bom + pom + import + ${arquillian-cube.version} + + + + org.jboss.arquillian + arquillian-bom + pom + import + ${arquillian-core.version} + + + junit + junit + ${junit.version} + test + + + org.slf4j + slf4j-bom + ${slf4j-api.version} + test + +---- + +Once this is done, we actually need to depend on Arquillian Cube and related artifacts, which we'll do by adding the +following to the `dependencies` section: + +[source,xml] +---- + + + org.arquillian.cube + arquillian-cube-docker + test + + + org.jboss.arquillian.junit + arquillian-junit-container + test + + + org.jboss.arquillian.junit + arquillian-junit-standalone + test + + + junit + junit + test + + + + org.slf4j + slf4j-api + test + + + org.slf4j + slf4j-simple + test + +---- + +while we'll have to remove the following ones: + +[source,xml] +---- + + + + + + + + + + + + + + +---- + +Last moves with our POM, let's add the following to the `wildfly-maven-plugin` configuration: + +[source,xml] +---- + + org.wildfly.plugins + wildfly-maven-plugin + ${version.wildfly.maven.plugin} + + + ${project.basedir}/docker-build/server + true + +---- + +and let the `maven-clean-plugin` take care of such directory when cleaning things up, too: + +[source,xml] +---- + + org.apache.maven.plugins + maven-clean-plugin + 3.3.2 + + + + + ${project.basedir}/docker-build/server + + + + +---- + +That's it, we're done with the POM, let's move on and see how the `arquillian.xml` file should be configured. + + +=== Update `arquillian.xml` configuration + +This is easy, we don't need a `wildfly` container anymore, so let's remove it. + +[source,xml] +---- + + + + + +---- + +Then we need to configure the `docker` extension, specifically we'll just set the `dockerContainersFile` property, +i.e. the path for the `docker-compose.yml` file: + +[source,xml] +---- + + ./docker-compose.yml + +---- + +With all the above in place, the only thing left is the test class. + +=== Create a test class for testing on Docker + +Add the following contents to a new `GettingStartedDockerIT.java` class: + +[source,java] +---- +package org.wildfly.examples; + +import jakarta.ws.rs.client.Client; +import jakarta.ws.rs.client.ClientBuilder; +import jakarta.ws.rs.core.Response; +import org.arquillian.cube.HostIp; +import org.arquillian.cube.HostPort; +import org.jboss.arquillian.junit.Arquillian; +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.net.URI; + +/** + * Run integration tests with Arquillian to be able to test CDI beans + */ +@RunWith(Arquillian.class) +public class GettingStartedDockerIT { + + @HostIp + private String wildflyIp; + + @HostPort(containerName = "wildfly", value = 8080) + int wildflyPort; + + @Test + public void testHelloEndpoint() { + try (Client client = ClientBuilder.newClient()) { + final String name = "World"; + Response response = client + .target(URI.create("http://" + wildflyIp + ":" + wildflyPort + "/")) + .path("/hello/" + name) + .request() + .get(); + + Assert.assertEquals(200, response.getStatus()); + Assert.assertEquals(String.format("Hello '%s'.", name), response.readEntity(String.class)); + + } + } +} +---- + +As you can see, it's similar to the existing `GettingStartedApplicationIT.java` test class that the Maven archetype +execution created for us in the original example, but we use a different runner, and inject the Docker container IP +address and the host port which is mapping the exposed `8080` port. + +At this point we can remove the two existing test classes, i.e. `GettingStartedServiceIT` and +`GettingStartedApplicationIT.java`. + +=== Run the test + +That's it, we can run Docker integration test by issuing the following command: + +[source,shell] +---- +mvn clean install +---- + +and we'll see how Arquillian Cube will gather the docker extension configuration, then summarize the container definition, +and eventually run the test: + +[source,shell] +---- +[INFO] ------------------------------------------------------- +[INFO] T E S T S +[INFO] ------------------------------------------------------- +[INFO] Running org.wildfly.examples.GettingStartedDockerIT +... +Jan 20, 2025 6:06:06 PM org.arquillian.cube.docker.impl.client.CubeDockerConfigurationResolver resolveSystemDefaultSetup +INFO: Connected to docker (fburzigo-thinkpadp1gen3.rmtit.csb) using default settings version: 24.0.5 kernel: 6.11.4-201.fc40.x86_64 +CubeDockerConfiguration: + serverUri = unix:///var/run/docker.sock + tlsVerify = false + dockerServerIp = localhost + definitionFormat = COMPOSE + clean = false + removeVolumes = true + dockerContainers = containers: + wildfly: + alwaysPull: false + buildImage: + dockerfileLocation: docker-build + noCache: true + remove: true + killContainer: false + manual: false + networkMode: front-tier + networks: + - front-tier + portBindings: !!set + 9991->9990/tcp: null + 8081->8080/tcp: null + readonlyRootfs: false + removeVolumes: true +networks: + front-tier: + driver: bridge + + +[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 16.69 s -- in org.wildfly.examples.GettingStartedDockerIT + +---- + +== In conclusion + +Testing a WildFly application directly on Docker will make the test more similar to the actual environment where +it will be run. +Arquillian Cube provides an easy and effective way to test on Docker, with almost no configuration and instrumentation +changes with respect to existing Arquillian based tests. + +The code for the example application which is described in this article is here: https://github.com/fabiobrz/wildfly-mini-series-docker-cube + +Fabio Burzigotti \ No newline at end of file From 71b89725044dd3dfba45cff666a39cc90ef1ad70 Mon Sep 17 00:00:00 2001 From: "Wildfly.org CI" Date: Mon, 27 Jan 2025 17:27:53 +0000 Subject: [PATCH 2/2] Update 2025-01-21-testing-on-docker-with-cube.adoc blog date --- ...th-cube.adoc => 2025-01-27-testing-on-docker-with-cube.adoc} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename _posts/{2025-01-21-testing-on-docker-with-cube.adoc => 2025-01-27-testing-on-docker-with-cube.adoc} (99%) diff --git a/_posts/2025-01-21-testing-on-docker-with-cube.adoc b/_posts/2025-01-27-testing-on-docker-with-cube.adoc similarity index 99% rename from _posts/2025-01-21-testing-on-docker-with-cube.adoc rename to _posts/2025-01-27-testing-on-docker-with-cube.adoc index 26845b9b9..6cac02399 100644 --- a/_posts/2025-01-21-testing-on-docker-with-cube.adoc +++ b/_posts/2025-01-27-testing-on-docker-with-cube.adoc @@ -1,7 +1,7 @@ --- layout: post title: Testing WildFly applications on Docker with Arquillian Cube -date: 2025-01-21 +date: 2025-01-27 tags: wildfly docker arquillian cube containers synopsis: Arquillian Cube is an Arquillian extension that provides an easy way to test a WildFly containerized application on Docker author: fabiobrz