We have also added a set of utility classes to easy testing of a state machine instances. These are used in a framework itself but are also very useful for end users.
StateMachineTestPlanBuilder
is used to build a StateMachineTestPlan
which then have one method test()
which runs a plan.
StateMachineTestPlanBuilder
contains a fluent builder api to add
steps into a plan and during these steps you can send events and check
various conditions like state changes, transitions and extended state
variables.
Let’s take a simple StateMachine
build using below example:
private StateMachine<String, String> buildMachine() throws Exception { StateMachineBuilder.Builder<String, String> builder = StateMachineBuilder.builder(); builder.configureConfiguration() .withConfiguration() .taskExecutor(new SyncTaskExecutor()) .autoStartup(true); builder.configureStates() .withStates() .initial("SI") .state("S1"); builder.configureTransitions() .withExternal() .source("SI").target("S1") .event("E1") .action(c -> { c.getExtendedState().getVariables().put("key1", "value1"); }); return builder.build(); }
In below test plan we have two steps, first we check that initial
state SI
is indeed set, secondly we send an event E1
and expect
one state change to happen and machine to end up into a state S1
.
StateMachine<String, String> machine = buildMachine(); StateMachineTestPlan<String, String> plan = StateMachineTestPlanBuilder.<String, String>builder() .defaultAwaitTime(2) .stateMachine(machine) .step() .expectStates("SI") .and() .step() .sendEvent("E1") .expectStateChanged(1) .expectStates("S1") .expectVariable("key1") .expectVariable("key1", "value1") .expectVariableWith(hasKey("key1")) .expectVariableWith(hasValue("value1")) .expectVariableWith(hasEntry("key1", "value1")) .expectVariableWith(not(hasKey("key2"))) .and() .build(); plan.test();
These utilities are also used within a framework to test distributed state machine features and multiple machines can be added to a plan. If multiple machines are added then it is also possible to choose if event is sent to particular, random or all machines.
Above testing example uses hamcrest imports:
import static org.hamcrest.CoreMatchers.not; import static org.hamcrest.collection.IsMapContaining.hasKey; import static org.hamcrest.collection.IsMapContaining.hasValue; import static org.hamcrest.collection.IsMapContaining.hasEntry;
Tip | |
---|---|
All possible options for expected are documented in javadocs StateMachineTestPlanStepBuilder. |