io.camunda.process.test.api.CamundaProcessTestExtension Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of camunda-process-test-java Show documentation
Show all versions of camunda-process-test-java Show documentation
Camunda's testing library for processes and process applications with Java
/*
* Copyright © 2017 camunda services GmbH ([email protected])
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.camunda.process.test.api;
import static org.junit.platform.commons.util.ReflectionUtils.makeAccessible;
import io.camunda.process.test.impl.assertions.CamundaDataSource;
import io.camunda.process.test.impl.containers.CamundaContainer;
import io.camunda.process.test.impl.extension.CamundaProcessTestContextImpl;
import io.camunda.process.test.impl.runtime.CamundaContainerRuntime;
import io.camunda.process.test.impl.runtime.CamundaContainerRuntimeBuilder;
import io.camunda.process.test.impl.testresult.CamundaProcessTestResultCollector;
import io.camunda.process.test.impl.testresult.CamundaProcessTestResultPrinter;
import io.camunda.process.test.impl.testresult.ProcessTestResult;
import io.camunda.zeebe.client.ZeebeClient;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Supplier;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
import org.junit.platform.commons.util.ExceptionUtils;
import org.junit.platform.commons.util.ReflectionUtils;
/**
* A JUnit extension that provides the runtime for process tests.
*
* Before each test method:
*
*
* - Start the runtime
*
- Inject a {@link ZeebeClient} to a field in the test class
*
- Inject a {@link CamundaProcessTestContext} to a field in the test class
*
*
* After each test method:
*
*
* - Close created {@link ZeebeClient}s
*
- Stop the runtime
*
*/
public class CamundaProcessTestExtension implements BeforeEachCallback, AfterEachCallback {
/** The JUnit extension namespace to store the runtime and context. */
public static final Namespace NAMESPACE = Namespace.create(CamundaProcessTestExtension.class);
/** The JUnit extension store key of the runtime. */
public static final String STORE_KEY_RUNTIME = "camunda-process-test-runtime";
/** The JUnit extension store key of the context. */
public static final String STORE_KEY_CONTEXT = "camunda-process-test-context";
private final List createdClients = new ArrayList<>();
private final CamundaContainerRuntimeBuilder containerRuntimeBuilder;
private final CamundaProcessTestResultPrinter processTestResultPrinter;
private CamundaContainerRuntime containerRuntime;
private CamundaProcessTestResultCollector processTestResultCollector;
CamundaProcessTestExtension(
final CamundaContainerRuntimeBuilder containerRuntimeBuilder,
final Consumer testResultPrintStream) {
this.containerRuntimeBuilder = containerRuntimeBuilder;
processTestResultPrinter = new CamundaProcessTestResultPrinter(testResultPrintStream);
}
/**
* Creates a new instance of the extension. Can be used to configure the runtime.
*
* Example usage:
*
*
* public class MyProcessTest {
*
* @RegisterExtension
* public CamundaProcessTestExtension extension =
* new CamundaProcessTestExtension().withCamundaVersion("8.6.0");
*
* }
*
*/
public CamundaProcessTestExtension() {
this(CamundaContainerRuntime.newBuilder(), System.err::println);
}
@Override
public void beforeEach(final ExtensionContext context) throws Exception {
// create runtime
containerRuntime = containerRuntimeBuilder.build();
containerRuntime.start();
final CamundaProcessTestContext camundaProcessTestContext =
new CamundaProcessTestContextImpl(
containerRuntime.getCamundaContainer(),
containerRuntime.getConnectorsContainer(),
createdClients::add);
// inject fields
try {
injectField(context, ZeebeClient.class, camundaProcessTestContext::createClient);
injectField(context, CamundaProcessTestContext.class, () -> camundaProcessTestContext);
} catch (final Exception e) {
createdClients.forEach(ZeebeClient::close);
containerRuntime.close();
throw e;
}
// put in store
final Store store = context.getStore(NAMESPACE);
store.put(STORE_KEY_RUNTIME, containerRuntime);
store.put(STORE_KEY_CONTEXT, camundaProcessTestContext);
// initialize assertions
final CamundaDataSource dataSource = createDataSource(containerRuntime);
CamundaAssert.initialize(dataSource);
// initialize result collector
processTestResultCollector = new CamundaProcessTestResultCollector(dataSource);
}
private void injectField(
final ExtensionContext context,
final Class injectionType,
final Supplier injectionValue) {
context
.getRequiredTestInstances()
.getAllInstances()
.forEach(instance -> injectField(instance, injectionType, injectionValue));
}
private void injectField(
final Object testInstance, final Class injectionType, final Supplier injectionValue) {
ReflectionUtils.findFields(
testInstance.getClass(),
field ->
ReflectionUtils.isNotStatic(field)
&& field.getType().isAssignableFrom(injectionType),
ReflectionUtils.HierarchyTraversalMode.TOP_DOWN)
.forEach(
field -> {
try {
makeAccessible(field).set(testInstance, injectionValue.get());
} catch (final Throwable t) {
ExceptionUtils.throwAsUncheckedException(t);
}
});
}
private CamundaDataSource createDataSource(final CamundaContainerRuntime containerRuntime) {
final CamundaContainer camundaContainer = containerRuntime.getCamundaContainer();
return new CamundaDataSource(camundaContainer.getRestApiAddress().toString());
}
@Override
public void afterEach(final ExtensionContext extensionContext) throws Exception {
// collect test results
final ProcessTestResult testResult = processTestResultCollector.collect();
// reset assertions
CamundaAssert.reset();
// close all created clients
createdClients.forEach(ZeebeClient::close);
// close the runtime
containerRuntime.close();
// print test results
if (isTestFailed(extensionContext)) {
processTestResultPrinter.print(testResult);
}
}
private static boolean isTestFailed(final ExtensionContext extensionContext) {
return extensionContext.getExecutionException().isPresent();
}
// ============ Configuration options =================
/**
* Configure the Camunda version of the runtime.
*
* @param camundaVersion the version to use
* @return the extension builder
*/
public CamundaProcessTestExtension withCamundaVersion(final String camundaVersion) {
containerRuntimeBuilder
.withCamundaDockerImageVersion(camundaVersion)
.withConnectorsDockerImageVersion(camundaVersion);
return this;
}
/**
* Configure the Camunda Docker image name of the runtime.
*
* @param dockerImageName the Docker image name to use
* @return the extension builder
*/
public CamundaProcessTestExtension withCamundaDockerImageName(final String dockerImageName) {
containerRuntimeBuilder.withCamundaDockerImageName(dockerImageName);
return this;
}
/**
* Add environment variables to the Camunda runtime.
*
* @param envVars environment variables to add
* @return the extension builder
*/
public CamundaProcessTestExtension withCamundaEnv(final Map envVars) {
containerRuntimeBuilder.withCamundaEnv(envVars);
return this;
}
/**
* Add an environment variable to the Camunda runtime.
*
* @param name the variable name
* @param value the variable value
* @return the extension builder
*/
public CamundaProcessTestExtension withCamundaEnv(final String name, final String value) {
containerRuntimeBuilder.withCamundaEnv(name, value);
return this;
}
/**
* Add an exposed port to the Camunda runtime.
*
* @param port the port to add
* @return the extension builder
*/
public CamundaProcessTestExtension withCamundaExposedPort(final int port) {
containerRuntimeBuilder.withCamundaExposedPort(port);
return this;
}
/**
* Enable or disable the Connectors. By default, the Connectors are disabled.
*
* @param enabled set {@code true} to enable the Connectors
* @return the extension builder
*/
public CamundaProcessTestExtension withConnectorsEnabled(final boolean enabled) {
containerRuntimeBuilder.withConnectorsEnabled(enabled);
return this;
}
/**
* Configure the Connectors Docker image name of the runtime.
*
* @param dockerImageName the Docker image name to use
* @return the extension builder
*/
public CamundaProcessTestExtension withConnectorsDockerImageName(final String dockerImageName) {
containerRuntimeBuilder.withConnectorsDockerImageName(dockerImageName);
return this;
}
/**
* Configure the Connectors Docker image version of the runtime.
*
* @param dockerImageVersion the version to use
* @return the extension builder
*/
public CamundaProcessTestExtension withConnectorsDockerImageVersion(
final String dockerImageVersion) {
containerRuntimeBuilder.withConnectorsDockerImageVersion(dockerImageVersion);
return this;
}
/**
* Add environment variables to the Connectors runtime.
*
* @param envVars environment variables to add
* @return the extension builder
*/
public CamundaProcessTestExtension withConnectorsEnv(final Map envVars) {
containerRuntimeBuilder.withConnectorsEnv(envVars);
return this;
}
/**
* Add an environment variable to the Connectors runtime.
*
* @param name the variable name
* @param value the variable value
* @return the extension builder
*/
public CamundaProcessTestExtension withConnectorsEnv(final String name, final String value) {
containerRuntimeBuilder.withConnectorsEnv(name, value);
return this;
}
/**
* Add a secret to the Connectors runtime.
*
* @param name the name of the secret
* @param value the value of the secret
* @return the extension builder
*/
public CamundaProcessTestExtension withConnectorsSecret(final String name, final String value) {
containerRuntimeBuilder.withConnectorsSecret(name, value);
return this;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy