diff --git a/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlan.java b/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlan.java index 00b1dcd0..a19996d3 100644 --- a/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlan.java +++ b/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlan.java @@ -34,6 +34,7 @@ import java.util.concurrent.TimeUnit; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hamcrest.Matcher; +import org.springframework.messaging.Message; import org.springframework.statemachine.StateMachine; import org.springframework.statemachine.test.StateMachineTestPlanBuilder.StateMachineTestPlanStep; import org.springframework.statemachine.test.support.LatchStateMachineListener; @@ -119,7 +120,7 @@ public class StateMachineTestPlan { } } - if (step.sendEvent != null) { + if (!step.sendEvent.isEmpty()) { ArrayList> sendVia = new ArrayList>(); if (step.sendEventMachineId != null) { sendVia.add(stateMachines.get(step.sendEventMachineId)); @@ -131,13 +132,17 @@ public class StateMachineTestPlan { assertThat("Error finding machine to send via", sendVia, not(empty())); if (!step.sendEventParallel) { for (StateMachine machine : sendVia) { - log.info("Sending test event " + step.sendEvent + " via machine " + machine); - machine.sendEvent(step.sendEvent); + for (E event : step.sendEvent) { + log.info("Sending test event " + event + " via machine " + machine); + machine.sendEvent(event); + } } } else { - sendEventParallel(sendVia, step.sendEvent); + for (E event : step.sendEvent) { + sendEventParallel(sendVia, event); + } } - } else if (step.sendMessage != null) { + } else if (!step.sendMessage.isEmpty()) { ArrayList> sendVia = new ArrayList>(); if (step.sendEventMachineId != null) { sendVia.add(stateMachines.get(step.sendEventMachineId)); @@ -148,8 +153,10 @@ public class StateMachineTestPlan { } assertThat("Error finding machine to send via", sendVia, not(empty())); for (StateMachine machine : sendVia) { - log.info("Sending test event " + step.sendEvent + " via machine " + machine); - machine.sendEvent(step.sendMessage); + for (Message event : step.sendMessage) { + log.info("Sending test event " + event + " via machine " + machine); + machine.sendEvent(event); + } } } diff --git a/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlanBuilder.java b/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlanBuilder.java index 30d6e8df..e5700d05 100644 --- a/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlanBuilder.java +++ b/spring-statemachine-test/src/main/java/org/springframework/statemachine/test/StateMachineTestPlanBuilder.java @@ -110,8 +110,8 @@ public class StateMachineTestPlanBuilder { */ public class StateMachineTestPlanStepBuilder { - E sendEvent; - Message sendMessage; + final List sendEvent = new ArrayList(); + final List> sendMessage = new ArrayList>(); Object sendEventMachineId; boolean sendEventToAll = false; boolean sendEventParallel = false; @@ -156,6 +156,8 @@ public class StateMachineTestPlanBuilder { /** * Send an event {@code E}. In case multiple state machines * exists, a random one will be chosen to send this event. + * Multiple events can be defined which are then send in + * defined order. * * @param event the event * @return the state machine test plan step builder @@ -166,7 +168,8 @@ public class StateMachineTestPlanBuilder { /** * Send an event {@code E}. If {@code sendToAll} is set to {@code TRUE} event - * will be send to all existing machines. + * will be send to all existing machines. Multiple events can be defined + * which are then send in defined order. * * @param event the event * @param sendToAll send to all machines @@ -181,6 +184,7 @@ public class StateMachineTestPlanBuilder { * Send an event {@code E}. If {@code sendToAll} is set to {@code TRUE} event * will be send to all existing machines. If {@code sendPalallel} is set to * {@code TRUE} event to all machines will be send by parallel threads. + * Multiple events can be defined which are then send in defined order. * * @param event the event * @param sendToAll send to all machines @@ -188,7 +192,7 @@ public class StateMachineTestPlanBuilder { * @return the state machine test plan step builder */ public StateMachineTestPlanStepBuilder sendEvent(E event, boolean sendToAll, boolean sendParallel) { - this.sendEvent = event; + this.sendEvent.add(event); this.sendEventMachineId = null; this.sendEventToAll = sendToAll; this.sendEventParallel = sendParallel; @@ -197,21 +201,23 @@ public class StateMachineTestPlanBuilder { /** * Send an event {@code E} into a state machine identified - * by {@code machineId}. + * by {@code machineId}. Multiple events can be defined + * which are then send in defined order. * * @param event the event * @param machineId the machine identifier for sending event * @return the state machine test plan step builder */ public StateMachineTestPlanStepBuilder sendEvent(E event, Object machineId) { - this.sendEvent = event; + this.sendEvent.add(event); this.sendEventMachineId = machineId; return this; } /** * Send a message {@code Message}. In case multiple state machines - * exists, a random one will be chosen to send this event. + * exists, a random one will be chosen to send this event. Multiple + * events can be defined which are then send in defined order. * * @param event the event * @return the state machine test plan step builder @@ -222,14 +228,15 @@ public class StateMachineTestPlanBuilder { /** * Send a message {@code Message}. If {@code sendToAll} is set to {@code TRUE} event - * will be send to all existing machines. + * will be send to all existing machines.Multiple events can be defined which are + * then send in defined order. * * @param event the event * @param sendToAll send to all machines * @return the state machine test plan step builder */ public StateMachineTestPlanStepBuilder sendEvent(Message event, boolean sendToAll) { - this.sendMessage = event; + this.sendMessage.add(event); this.sendEventMachineId = null; this.sendEventToAll = sendToAll; return this; @@ -237,14 +244,15 @@ public class StateMachineTestPlanBuilder { /** * Send a message {@code Message} into a state machine identified - * by {@code machineId}. + * by {@code machineId}. Multiple events can be defined which are then + * send in defined order. * * @param event the event * @param machineId the machine identifier for sending event * @return the state machine test plan step builder */ public StateMachineTestPlanStepBuilder sendEvent(Message event, Object machineId) { - this.sendMessage = event; + this.sendMessage.add(event); this.sendEventMachineId = machineId; return this; } @@ -432,8 +440,8 @@ public class StateMachineTestPlanBuilder { } static class StateMachineTestPlanStep { - E sendEvent; - Message sendMessage; + final List sendEvent; + final List> sendMessage; Object sendEventMachineId; boolean sendEventToAll = false; boolean sendEventParallel = false; @@ -451,7 +459,7 @@ public class StateMachineTestPlanBuilder { final Collection expectVariableKeys; final Map expectVariables; - public StateMachineTestPlanStep(E sendEvent, Message sendMessage, Object sendEventMachineId, + public StateMachineTestPlanStep(List sendEvent, List> sendMessage, Object sendEventMachineId, boolean sendEventToAll, boolean sendEventParallel, Collection expectStates, Integer expectStateChanged, Integer expectStateEntered, Integer expectStateExited, Integer expectEventNotAccepted, Integer expectTransition, Integer expectTransitionStarted, diff --git a/spring-statemachine-test/src/test/java/org/springframework/statemachine/test/StateMachineTestingTests.java b/spring-statemachine-test/src/test/java/org/springframework/statemachine/test/StateMachineTestingTests.java index 43cb99d4..56fd5571 100644 --- a/spring-statemachine-test/src/test/java/org/springframework/statemachine/test/StateMachineTestingTests.java +++ b/spring-statemachine-test/src/test/java/org/springframework/statemachine/test/StateMachineTestingTests.java @@ -65,6 +65,28 @@ public class StateMachineTestingTests extends AbstractStateMachineTests { plan.test(); } + @SuppressWarnings("unchecked") + @Test + public void testMultipleEvents() throws Exception { + registerAndRefresh(Config3.class); + StateMachine machine = context.getBean(StateMachine.class); + + StateMachineTestPlan plan = + StateMachineTestPlanBuilder.builder() + .stateMachine(machine) + .step().expectStateMachineStarted(1).and() + .step().expectState("READY").and() + .step() + .sendEvent("DEPLOY") + .sendEvent("DEPLOY") + .expectStateChanged(6) + .expectState("READY") + .and() + .build(); + + plan.test(); + } + @Override protected AnnotationConfigApplicationContext buildContext() { return new AnnotationConfigApplicationContext(); @@ -142,4 +164,34 @@ public class StateMachineTestingTests extends AbstractStateMachineTests { } + @Configuration + @EnableStateMachine + static class Config3 extends StateMachineConfigurerAdapter { + + @Override + public void configure(StateMachineStateConfigurer states) + throws Exception { + states + .withStates() + .initial("READY") + .state("DEPLOYPREPARE", "DEPLOY") + .state("DEPLOYEXECUTE", "DEPLOY"); + } + + @Override + public void configure(StateMachineTransitionConfigurer transitions) + throws Exception { + transitions + .withExternal() + .source("READY").target("DEPLOYPREPARE") + .event("DEPLOY") + .and() + .withExternal() + .source("DEPLOYPREPARE").target("DEPLOYEXECUTE") + .and() + .withExternal() + .source("DEPLOYEXECUTE").target("READY"); + } + } + }