Junit5 extensions
Dekorate provides two junit5 extensions for:
- Kubernetes
- OpenShift
- Knative
These extensions are dekorate
aware and can read generated resources and configuration, in order to manage end to end
tests
for the annotated applications.
Features
- Environment conditions
- Container builds
- Apply generated manifests to test environment
- Inject test with:
- client
- application pod
Kubernetes extension for JUnit5
The kubernetes extension can be used by adding the following dependency:
<dependency>
<groupId>io.dekorate</groupId>
<artifactId>kubernetes-junit</artifactId>
<version>4.1.4</version>
</dependency>
This dependency gives access to @KubernetesIntegrationTest which is what enables the extension for your tests.
By adding the annotation to your test class the following things will happen:
- The extension will check if a kubernetes cluster is available (if not tests will be skipped).
- If
@DockerBuild
is present in the project, a docker build will be triggered. - All generated manifests will be applied.
- Will wait until applied resources are ready.
- Dependencies will be injected (e.g. KubernetesClient, Pod etc)
- Test will run
- Applied resources will be removed.
Dependency injection
Supported items for injection:
- KubernetesClient
- Pod (the application pod)
- KubernetesList (the list with all generated resources)
To inject one of this you need a field in the code annotated with @Inject.
For example:
@Inject
KubernetesClient client;
When injecting a Pod, it’s likely we need to specify the pod name. Since the pod name is not known in advance, we can use the deployment name instead.
If the deployment is named hello-world
then you can do something like:
@Inject
@Named("hello-world")
Pod pod;
Note: It is highly recommended to also add maven-failsafe-plugin
configuration so that integration tests only run in the integration-test
phase.
This is important since in the test
phase the application is not packaged. Here’s an example of how it you can configure the project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${version.maven-failsafe-plugin}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/*IT.class</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Integration Test Configuration
We can customize the deployment configuration within the test execution using the Kubernetes integration test annotation:
@KubernetesIntegrationTest(deployEnabled = true,
buildEnabled = true,
readinessTimeout = 300000,
additionalModules = {}
)
class KubernetesIT {
// ...
}
Field | Type | Description | Overridable using System Property | Default Value |
---|---|---|---|---|
deployEnabled | boolean | Flag to define whether the extension should automatically apply resources. | dekorate.test.deploy.enabled | true |
buildEnabled | boolean | Flag to define whether the extension should automatically perform container builds. | dekorate.test.build.enabled | true |
readinessTimeout | long | The amount of time in milliseconds to wait for application to become ready. | dekorate.test.readiness.timeout | 300000 |
additionalModules | String[] | List of additional modules to be loaded by the test framework. | dekorate.test.additional-modules |
related examples
OpenShift extension for JUnit5
Similarly, to using the kubernetes junit extension you can use the extension for OpenShift, by adding @OpenshiftIntegrationTest. To use that you need to add:
<dependency>
<groupId>io.dekorate</groupId>
<artifactId>openshift-junit</artifactId>
<version>4.1.4</version>
</dependency>
By adding the annotation to your test class the following things will happen:
- The extension will check if a kubernetes cluster is available (if not tests will be skipped).
- A docker build will be triggered.
- All generated manifests will be applied.
- Will wait until applied resources are ready.
- Dependencies will be injected (e.g. KubernetesClient, Pod etc)
- Test will run
- Applied resources will be removed.
Integration Test Configuration
We can customize the deployment configuration within the test execution using the OpenShift integration test annotation:
@OpenshiftIntegrationTest(deployEnabled = true,
buildEnabled = true,
pushEnabled = false,
imageStreamTagTimeout = 120000,
readinessTimeout = 300000,
additionalModules = {}
)
class OpenShiftIT {
// ...
}
Field | Type | Description | Overridable using System Property | Default Value |
---|---|---|---|---|
deployEnabled | boolean | Flag to define whether the extension should automatically apply resources. | dekorate.test.deploy.enabled | true |
buildEnabled | boolean | Flag to define whether the extension should automatically perform container builds. | dekorate.test.build.enabled | true |
pushEnabled | boolean | Flag to define whether the extension should automatically push image. | dekorate.test.openshift.push.enabled | false |
imageStreamTagTimeout | long | The amount of time in seconds to wait for the image stream tags to be available. | dekorate.test.openshift.image-stream.timeout | 120000 |
readinessTimeout | long | The amount of time in milliseconds to wait for application to become ready. | dekorate.test.readiness.timeout | 300000 |
additionalModules | String[] | List of additional modules to be loaded by the test framework. | dekorate.test.additional-modules |
related examples
- spring boot on openshift example
- spring boot with groovy on openshift example
- spring boot with gradle on openshift example
Knative extension for JUnit5
The knative extension can be used by adding the following dependency:
<dependency>
<groupId>io.dekorate</groupId>
<artifactId>knative-junit</artifactId>
<version>4.1.4</version>
</dependency>
This dependency gives access to @KnativeIntegrationTest which is what enables the extension for your tests.
By adding the annotation to your test class the following things will happen:
- The extension will check if a kubernetes cluster is available (if not tests will be skipped).
- If
@DockerBuild
is present in the project, a docker build will be triggered. - All generated manifests will be applied.
- Will wait until applied resources and the Knative services are ready.
- Dependencies will be injected (e.g. KnativeClient, Service, Knative Routes, etc)
- Test will run
- Applied resources will be removed.
Dependency injection
In addition to the supported items from the Kubernetes JUnit 5 extension, the following resources can be injected:
- KnativeClient
- Knative Service
- Knative Route (or the URL of the Knative route)
To inject one of this you need a field in the code annotated with @Inject.
For example:
@Inject
KnativeClient client;
When injecting the URL of a Route, it’s likely we need to specify the route name. For example, if the deployment is named hello-world
then you can do something like:
@Inject
@Named("hello-world")
URL knativeAppRouteUrl;
Note: It is highly recommended to also add maven-failsafe-plugin
configuration so that integration tests only run in the integration-test
phase.
This is important since in the test
phase the application is not packaged. Here’s an example of how it you can configure the project:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${version.maven-failsafe-plugin}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<phase>integration-test</phase>
<configuration>
<includes>
<include>**/*IT.class</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Integration Test Configuration
We can customize the deployment configuration within the test execution using the Knative integration test annotation:
@KnativeIntegrationTest(deployEnabled = true,
buildEnabled = true,
readinessTimeout = 300000,
additionalModules = {}
)
class KnativeIT {
// ...
}
Field | Type | Description | Overridable using System Property | Default Value |
---|---|---|---|---|
deployEnabled | boolean | Flag to define whether the extension should automatically apply resources. | dekorate.test.deploy.enabled | true |
buildEnabled | boolean | Flag to define whether the extension should automatically perform container builds. | dekorate.test.build.enabled | true |
readinessTimeout | long | The amount of time in milliseconds to wait for application to become ready. | dekorate.test.readiness.timeout | 300000 |
additionalModules | String[] | List of additional modules to be loaded by the test framework. | dekorate.test.additional-modules |
related examples
Configuration externalization
It is often desired to externalize configuration in configuration files, instead of hard coding things inside annotations.
Dekorate provides the ability to externalize configuration to configuration files (properties or yml). This can be done to either override the configuration values provided by annotations, or to use dekorate without annotations.
For supported frameworks, this is done out of the box, as long as the corresponding framework jar is present. The frameworks supporting this feature are:
- spring boot
- thorntail
For these frameworks, the use of annotations is optional, as everything may be configured via configuration files. Each annotation may be expressed using properties or yaml using the following steps.
- Each annotation property is expressed using a key/value pair.
- All keys start with the
dekorate.<annotation kind>.
prefix, whereannotation kind
is the annotation class name in lowercase, stripped of theApplication
suffix. - The remaining part of key is the annotation property name.
- For nesting properties the key is also nested following the previous rule.
For all other frameworks or generic java application this can be done with the use of the @Dekorate
annotation.
The presence of this annotation will trigger the dekorate processes. Dekorate will then look for application.properites
or application.yml
resources.
If present, they will be loaded. If not the default configuration will be used.
Examples:
The following annotation configuration:
@KubernetesApplication(labels=@Label(key="foo", value="bar"))
public class Main {
}
Can be expressed using properties:
dekorate.kubernetes.labels[0].key=foo
dekorate.kubernetes.labels[0].value=bar
or using yaml:
dekorate:
kubernetes:
labels:
- key: foo
value: bar
In the examples above, dekorate
is the prefix that we use to namespace
the dekorate configuration. kubernetes
defines the annotation kind (its @KubernetesApplication
in lower case and stripped of the Application
suffix).
labels
, key
and value
are the property names and since the Label
is nested under @KubernetesApplication
so are the properties.
The exact same example for OpenShift (where @OpenshiftApplication
is used instead) would be:
@OpenshiftApplication(labels=@Label(key="foo", value="bar"))
public class Main {
}
Can be expressed using properties:
dekorate.openshift.labels[0].key=foo
dekorate.openshift.labels[0].value=bar
or using yaml:
dekorate:
openshift:
labels:
- key: foo
value: bar
Spring Boot
For spring boot, dekorate will look for configuration under:
- application.properties
- application.yml
- application.yaml
Also, it will look for the same files under the kubernetes profile:
- application-kubernetes.properties
- application-kubernetes.yml
- application-kubernetes.yaml
Vert.x & generic Java
For generic java, if the @Dekorate annotation is present, then dekorate will look for confiugration under:
- application.properties
- application.yml
These files can be overridden using the configFiles
property on the @Dekorate
annotation.
For example:
A generic java application annotated with @Dekorate
:
import io.dekorate.annotation.Dekorate;
@Dekorate
public class Main {
//do stuff
}
During compilation kubernetes, OpenShift or both resources will be generated (depending on what dekorate jars are present in the classpath). These resources can be customized using properties:
dekorate.openshift.labels[0].key=foo
dekorate.openshift.labels[0].value=bar
or using yaml:
dekorate:
openshift:
labels:
- key: foo
value: bar
related examples
Testing Multi-Module projects
The Dekorate testing framework supports multi-module projects either using the OpenShift JUnit 5 extension or using the Kubernetes JUnit 5 extension.
A multi-module project consist of multiple modules, all using Dekorate to generate the cluster manifests and a tests
module that will run the integration tests:
multi-module-parent
└───module-1
└───module-2
└───tests
In the tests
module, we can now specify the location of the additional modules via the field additionalModules
which is part of the @OpenshiftIntegrationTest
and @KubernetesIntegrationTest
annotations:
@OpenshiftIntegrationTest(additionalModules = { "../module-1", "../module-2" })
class SpringBootForMultipleAppsOnOpenshiftIT {
@Inject
private KubernetesClient client;
@Inject
@Named("module-1")
Pod podForModuleOne;
@Inject
@Named("module-2")
Pod podForModuleTwo;
// ...
}
Doing so, the test framework will locate the Dekorate manifests that have been previously generated to build and deploy the application for each integration test.