All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.camunda.process.test.api.CamundaProcessTestExtension Maven / Gradle / Ivy

There is a newer version: 8.7.0-alpha2
Show newest version
/*
 * 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