https://github.com/t1/jee-testcontainers
testcontainers.org for Jakarta EE application servers
https://github.com/t1/jee-testcontainers
Last synced: about 1 year ago
JSON representation
testcontainers.org for Jakarta EE application servers
- Host: GitHub
- URL: https://github.com/t1/jee-testcontainers
- Owner: t1
- License: apache-2.0
- Created: 2019-12-03T08:11:32.000Z (over 6 years ago)
- Default Branch: trunk
- Last Pushed: 2025-04-11T22:48:20.000Z (over 1 year ago)
- Last Synced: 2025-04-11T23:34:06.948Z (over 1 year ago)
- Language: Java
- Size: 234 KB
- Stars: 2
- Watchers: 1
- Forks: 2
- Open Issues: 2
-
Metadata Files:
- Readme: README.adoc
- License: LICENSE
Awesome Lists containing this project
README
= JEE Testcontainers image:https://maven-badges.herokuapp.com/maven-central/com.github.t1/jee-testcontainers/badge.svg[link=https://search.maven.org/artifact/com.github.t1/jee-testcontainers] image:https://github.com/t1/jee-testcontainers/actions/workflows/maven.yml/badge.svg[link=https://github.com/t1/jee-testcontainers/actions/workflows/maven.yml]
Simply start and stop Jakarta EE containers and deploy applications for your integration tests.
This is an extension to https://testcontainers.org[Testcontainers] for Jakarta EE application servers, so Docker is used under the hood, but you don't need to write, e.g., a Dockerfile.
Prototypical Example:
[source,java]
---------------------------------------------------------------
@Testcontainers
public class MyAppIT {
@Container static JeeContainer CONTAINER = JeeContainer.create()
.withDeployment("target/my-app.war");
@Test void shouldGetStatusResponse() {
String body = CONTAINER.target().request(APPLICATION_JSON_TYPE).get(String.class);
then(body).isEqualTo("{\"status\":\"okay\"}");
}
}
---------------------------------------------------------------
Or if you have an implementation of Microprofile Rest Client on your test classpath:
[source,java]
---------------------------------------------------------------
@Testcontainers
public class MyAppIT {
@Container static JeeContainer CONTAINER = JeeContainer.create()
.withDeployment("target/my-app.war");
@Data public static class Status {
String condition;
}
public interface StatusApi {
@GET Status getStatus();
}
@Test void shouldGetStatusResponse() {
StatusApi body = CONTAINER.restClient(StatusApi.class);
Status status = body.getStatus();
then(status.getCondition()).isEqualTo("okay");
}
}
---------------------------------------------------------------
The console output of the container is piped to the test's output, STDOUT in green and STDERR in blue.
== Deployments
As seen in the prototypical example above, you can install an application by calling `.withDeployment()`.
Instead of a local file, you can also install from an URL.
Or you can use a maven URN like `urn:mvn:org.jolokia:jolokia-war-unsecured:1.6.3:war`.
Finally, you can also build your deployment manually, by adding the classes and other files you want included.
For some details, see below.
== Container Image
Set the system property `jee-testcontainer` to one of the keys in the following table to select the corresponding container.
Ideally you shouldn't have to care about what server your application runs on, or you may even want to test it in multiple containers.
Then you can run your test suite in your CI pipeline with different system properties.
You can append a tag to the `jee-testcontainer` separated by a colon `:`.
This is often simply the version of the container; e.g. `wildfly:27.0.0.Final`.
[options="header",cols="15%,15%,40%,30%"]
|=======================
| Key | Container | Docker Image | Notes
| `wildfly` | https://wildfly.org[WildFly] | https://quay.io/repository/wildfly/wildfly[`wildfly/wildfly`] | default container on https://quay.io[`quay.io`]
| `open-liberty` | https://openliberty.io[Open Liberty] | https://hub.docker.com/_/open-liberty[`open-liberty`] | we add `server.xml` with features `javaee-10.0` and `microProfile-5.0`
| `tomee` | https://tomee.apache.org[TomEE] | https://hub.docker.com/_/tomee[`tomee`] | Official image
| `payara` | https://www.payara.fish[Payara] | https://hub.docker.com/r/payara/server-full[`payara`] | not an 'official' image on Docker-Hub
// TODO support | `glassfish` | https://javaee.github.io/glassfish/[Glassfish] | https://hub.docker.com/_/glassfish[`glassfish`] | deprecated image!
|=======================
== Reuse
You can reuse a running container instance for all tests as long as the config doesn't change, by calling `withReuse(true)`.
This feature is marked as unstable from testcontainers.org.
You can achieve the same by setting the system property `testcontainer-reuse` to `true`, which comes in handy when you need it only for certain launch configurations, i.e. local or on CI.
== Ports
By default, the main port exposed by the container (which accidentally is 8080 in all currently supported JEE servers) is published/bound to a random free port.
You can bind it to a fixed port by calling `JeeContainer#withMainPortBoundToFixedPort(int hostPort)`.
Or you can set the `testcontainer-with-main-port-bound-to-fixed-port` system property for the same effect.
Similarly, you can publish any port by calling `JeeContainer#withPortBoundToFixedPort(int hostPort, int containerPort)`.
Fixing port numbers may be convenient in some cases, but you shouldn't do this without a good reason.
== Modifications
You can modify the deployable in two ways.
You can have multiple and repeated modification to, e.g., rename the file and add multiple libraries.
=== Rename
[source,java]
---------------------------------------------------------------
import static com.github.t1.testcontainers.jee.NamedAsMod.namedAs;
@Testcontainers
public class MyAppIT {
@Container static JeeContainer CONTAINER = JeeContainer.create()
.withDeployment("target/my-app.war", namedAs("foo.war"));
}
---------------------------------------------------------------
=== Add Library
[source,java]
---------------------------------------------------------------
import static com.github.t1.testcontainers.jee.AddLibMod.addLib;
@Testcontainers
public class MyAppIT {
@Container static JeeContainer CONTAINER = JeeContainer.create()
.withDeployment("target/my-app.war", addLib("urn:mvn:org.jolokia:jolokia-war-unsecured:1.6.3:war"));
}
---------------------------------------------------------------
=== Add Config
[source,java]
---------------------------------------------------------------
import static com.github.t1.testcontainers.jee.ConfigMod.config;
@Testcontainers
public class MyAppIT {
@Container static JeeContainer CONTAINER = JeeContainer.create()
.withDeployment("target/my-app.war", config("foo", "bar"));
}
---------------------------------------------------------------
Configure the https://microprofile.io/project/eclipse/microprofile-config[MP Config] key `foo` to be `bar`.
Creates or appends to `WEB-INF/classes/META-INF/microprofile-config.properties`.
== Container Configuration
You can configure the log level of a logger, e.g. by calling `withLogLevel`
(at the moment, this only works for WildFly containers, but we're open for PRs 😀).
You can also configure a data source by calling `withDataSource(DB)`, where `DB` is a `JdbcDatabaseContainer` (currently only `PostgreSQLContainer` and only on `WildFly`).
For `WildFly`, you can also call arbitrary `CLI` commands by calling `withCli`.
Apart from that, you can't currently configure anything else for your application, e.g. add message queues.
I will add such things whenever I need it, but again: PRs are welcome.
// TODO health wait strategy
// TODO configure message queues, etc.
== Building A Test Deployable
There's a very limited support to build a `war` deployable from scratch.
See the API of the https://github.com/t1/jee-testcontainers/blob/trunk/src/main/java/com/github/t1/testcontainers/tools/DeployableBuilder.java[DeployableBuilder] class for details.
If you need more, maybe https://github.com/shrinkwrap/shrinkwrap[ShrinkWrap] can help, but I haven't tried that in combination, yet.
== Breaking Changes (Major Versions)
=== 3.0.0
* Drop support for Java 11, because JEE 11 and the libraries used for JEE 11 (e.g. Smallrye Config) require Java 17.