Imixs-Workflow - Simulation and Testing

The Imixs-Workflow project provides a services and test environments to simulate and test the processing life cycle of a specific model or process instance.

Simulate a Processing Live Cycle

The WorkflowService provides a method called evalNextTask. This method evaluates the next task for a process instance (workitem) based on the current model definition. A Workitem must at least provide the properties $TASKID and $EVENTID. The method call can be helpful in many cases when a business logic just need to compute the next logical BPMN Task Element which will be assigned with a given process instance.

try {
	// simulate the processing life cycle of a given workitem
	ItemCollection nextTaskEnity = workflowService.evalNextTask(workitem);
} catch (ModelException e) {
	throw new PluginException(DocumentComposerPlugin.class.getSimpleName(), e.getErrorCode(), e.getMessage());
}

Note: During the evaluation life-cycle more than one events can be evaluated. This depends on the model definition which can define follow-up-events, split-events and conditional events. The evalNextTask method did not persist the process instance or execute any plugin or adapter classes.

Testing with the WorkflowMockEnvironment

The Test class WorkflowMockEnvironment mocks a full workflow environment including a in-memory-database. The WorkflowMockEnvironment can be used for more complex integration tests using JUnit 5 or higher.

import static org.junit.jupiter.api.Assertions.assertEquals;
import org.imixs.workflow.ItemCollection;
import org.imixs.workflow.exceptions.*;
import org.junit.Assert;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class TestTemplate {

	protected WorkflowMockEnvironment workflowEnvironment;

	/**
	 * Setup the Mock environment
	 */
	@BeforeEach
	public void setUp() throws PluginException, ModelException {
		workflowEnvironment = new WorkflowMockEnvironment();
		workflowEnvironment.setUp();
		workflowEnvironment.loadBPMNModel("/bpmn/TestWorkflowService.bpmn");
	}

	/**
	 * This test simulates a workflowService process call.
	 */
	@Test
	public void testProcessSimple() {
		try {
			// load a test workitem
			ItemCollection workitem = workflowEnvironment.getDocumentService().load("W0000-00001");
			workitem.model("1.0.0").task(100).event(10);
			workitem = workflowEnvironment.workflowService.processWorkItem(workitem);
			// expected new task is 200
			assertEquals(200, workitem.getTaskID());
		} catch (AccessDeniedException | ProcessingErrorException | PluginException | ModelException e) {
			Assert.fail(e.getMessage());
		}
	}

	/**
	 * Test a complex workflow process with conditional events
	 */
	@Test
	public void testConditionalEvent1()
			throws AccessDeniedException, ProcessingErrorException, PluginException, ModelException {

		workflowEnvironment.loadBPMNModel("/bpmn/conditional_event1.bpmn");
		// load test workitem
		ItemCollection workitem = workflowEnvironment.getDocumentService().load("W0000-00001");
		workitem.replaceItemValue("_budget", 99);
		workitem.model("1.0.0").task(1000).event(10);
		// test _budget<100 => 1200
		workitem = workflowEnvironment.workflowService.processWorkItem(workitem);
		Assert.assertEquals(1200, workitem.getTaskID());
		// test _budget>100 => 1100
		workitem.replaceItemValue("_budget", 9999);
		workitem.model("1.0.0").task(1000).event(10);
		workitem = workflowEnvironment.workflowService.processWorkItem(workitem);
		Assert.assertEquals(1100, workitem.getTaskID());
	}
}

How to setup a test case

To setup a test case the Imixs WorkflowMockEnvironment provides a setup method to initialize the environment and a loadBPMNModel method to load a test model. To setup the environment it is recommended to call the setup() method in a org.junit.jupiter.api.BeforeEach annotated init method:

@BeforeEach
public void setUp() throws PluginException, ModelException {
	workflowEnvironment = new WorkflowMockEnvironment();
	workflowEnvironment.setUp();
	workflowEnvironment.loadBPMNModel("/bpmn/TestWorkflowService.bpmn");
}

How to test business cases

The main goal of the WorkflowMockEnvironment is to test business logic of a specific workflow model. A workflow instance can be created form a empty ItemCollection and tested with any kind of data.

// Load a test model
workflowEnvironment.loadBPMNModel("/bpmn/myModel.bpmn");
// Create a workflow instance with some business data
ItemCollection workitem = new ItemCollection();
workitem.replaceItemValue("_budget", 99);
// process the workflow instance....
workitem.model("1.0.0").task(1000).event(10);
workitem = workflowEnvironment.workflowService.processWorkItem(workitem);
// evaluate the results....
Assert.assertEquals(1200, workitem.getTaskID());

Mock Imixs Adapter Classes

The WorkflowMockEnvironment also allows you to test custom Imixs Workflow GenericAdapter or SignalAdapter classes. You just need to call the method registerAdapter(...) method before you call setup(). See the following example:


public class MyAdapterTest {

	@InjectMocks
	protected MyImixsAdapter myAdapter;

	protected WorkflowMockEnvironment workflowEnvironment;

	@BeforeEach
	public void setUp() throws PluginException, ModelException {
		// Ensures that @Mock and @InjectMocks annotations are processed
		MockitoAnnotations.openMocks(this);
		workflowEnvironment = new WorkflowMockEnvironment();

		// register AccessAdapter Mock
		workflowEnvironment.registerAdapter(accessAdapter);

		// Setup Environment
		workflowEnvironment.setUp();
	}
	.....
}