public void Start( AsyncPassiveStateMachine <int, int> machine, bool entryActionExecuted) { "establish an initialized state machine".x(() => { machine = new AsyncPassiveStateMachine <int, int>(); machine.AddExtension(this.testExtension); machine.In(TestState) .ExecuteOnEntry(() => entryActionExecuted = true); machine.Initialize(TestState); }); "when starting the state machine".x(() => machine.Start()); "should set current state of state machine to state to which it is initialized".x(() => this.testExtension.CurrentState.Should().Be(TestState)); "should execute entry action of state to which state machine is initialized".x(() => entryActionExecuted.Should().BeTrue()); }
public void BeforeExecutingEntryActions( AsyncPassiveStateMachine<string, int> machine, IExtension<string, int> extension) { "establish an extension".x(() => extension = A.Fake<IExtension<string, int>>()); "establish a state machine using the extension".x(async () => { machine = new AsyncPassiveStateMachine<string, int>(Name); machine.AddExtension(extension); machine.In("0") .On(1).Goto("1"); await machine.Initialize("0"); await machine.Start(); }); "when firing an event onto the state machine".x(() => machine.Fire(1)); "it should call EnteringState on registered extensions for target state".x(() => A.CallTo(() => extension.EnteringState( A<IStateMachineInformation<string, int>>.That.Matches(x => x.Name == Name && x.CurrentStateId == "1"), A<IState<string, int>>.That.Matches(x => x.Id == "1"), A<ITransitionContext<string, int>>.That.Matches(x => x.EventId.Value == 1))) .MustHaveHappened()); }
public void Reinitialization( AsyncPassiveStateMachine <int, int> machine, Exception receivedException) { "establish an initialized state machine".x(async() => { machine = new AsyncPassiveStateMachine <int, int>(); await machine.Initialize(TestState); }); "when state machine is initialized again".x(async() => { try { await machine.Initialize(TestState); } catch (Exception e) { receivedException = e; } }); "should throw an invalid operation exception".x(() => { receivedException .Should().BeAssignableTo <InvalidOperationException>(); receivedException.Message .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }
public void CustomTypesForStatesAndEvents( AsyncPassiveStateMachine <MyState, MyEvent> machine, bool arrivedInStateB) { "establish a state machine with custom types for states and events"._(async() => { machine = new AsyncPassiveStateMachine <MyState, MyEvent>(); machine.In(new MyState("A")) .On(new MyEvent(1)).Goto(new MyState("B")); machine.In(new MyState("B")) .ExecuteOnEntry(() => arrivedInStateB = true); await machine.Initialize(new MyState("A")); await machine.Start(); }); "when using the state machine"._(() => machine.Fire(new MyEvent(1))); "it should use equals to compare states and events"._(() => arrivedInStateB.Should().BeTrue("state B should be current state")); }
public void EventsQueueing( IAsyncStateMachine <string, int> machine) { const int firstEvent = 0; const int secondEvent = 1; bool arrived = false; "establish a passive state machine with transitions".x(() => { machine = new AsyncPassiveStateMachine <string, int>(); machine.In("A").On(firstEvent).Goto("B"); machine.In("B").On(secondEvent).Goto("C"); machine.In("C").ExecuteOnEntry(() => arrived = true); machine.Initialize("A"); }); "when firing an event onto the state machine".x(() => { machine.Fire(firstEvent); machine.Fire(secondEvent); machine.Start(); }); "it should queue event at the end".x(() => arrived.Should().BeTrue("state machine should arrive at destination state")); }
public void OtherwiseGuard( AsyncPassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with otherwise guard and no machting other guard".x(async() => { machine = new AsyncPassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => Task.FromResult(false)).Goto(ErrorState) .Otherwise().Goto(DestinationState); await machine.Initialize(SourceState); await machine.Start(); }); "when an event is fired".x(() => machine.Fire(Event)); "it should_take_transition_guarded_with_otherwise".x(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void EventArgument( AsyncPassiveStateMachine <int, int> machine, int passedArgument) { const int argument = 17; "establish a state machine with an exit action taking an event argument".x(() => { machine = new AsyncPassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnExit((int a) => passedArgument = a) .On(Event).Goto(AnotherState); machine.In(AnotherState) .ExecuteOnEntry((int a) => passedArgument = a); }); "when leaving the state".x(async() => { await machine.Initialize(State); await machine.Start(); await machine.Fire(Event, argument); }); "it should pass event argument to exit action".x(() => passedArgument.Should().Be(argument)); }
public void MatchingGuard( AsyncPassiveStateMachine <int, int> machine, CurrentStateExtension currentStateExtension) { "establish a state machine with guarded transitions".x(async() => { machine = new AsyncPassiveStateMachine <int, int>(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => false).Goto(ErrorState) .If(async() => await Task.FromResult(false)).Goto(ErrorState) .If(async() => await Task.FromResult(true)).Goto(DestinationState) .If(() => true).Goto(ErrorState) .Otherwise().Goto(ErrorState); await machine.Initialize(SourceState); await machine.Start(); }); "when an event is fired".x(() => machine.Fire(Event)); "it should take transition guarded with first matching guard".x(() => currentStateExtension.CurrentState.Should().Be(DestinationState)); }
public void ExitAction( AsyncPassiveStateMachine <int, int> machine, bool exitActionExecuted, bool asyncExitActionExecuted) { "establish a state machine with exit action on a state".x(() => { machine = new AsyncPassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnExit(() => exitActionExecuted = true) .ExecuteOnExit(async() => { asyncExitActionExecuted = true; await Task.Yield(); }) .On(Event).Goto(AnotherState); }); "when leaving the state".x(async() => { await machine.Initialize(State); await machine.Start(); await machine.Fire(Event); }); "it should execute the synchronous exit action".x(() => exitActionExecuted.Should().BeTrue()); "it should execute the asynchronous exit action".x(() => asyncExitActionExecuted.Should().BeTrue()); }
public void LoadingNonInitializedStateMachine( AsyncPassiveStateMachine <State, Event> loadedMachine) { "when a non-initialized state machine is loaded".x(async() => { var loader = new StateMachineLoader <State>(); loader.SetCurrentState(new Initializable <State>()); loader.SetHistoryStates(new Dictionary <State, State>()); var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <State, Event>(); SetupStates(stateMachineDefinitionBuilder); loadedMachine = stateMachineDefinitionBuilder .WithInitialState(State.A) .Build() .CreatePassiveStateMachine(); await loadedMachine.Load(loader); }); "it should not be initialized already".x(async() => { var stateMachineSaver = new StateMachineSaver <State>(); await loadedMachine.Save(stateMachineSaver); stateMachineSaver .CurrentStateId .IsInitialized .Should() .BeFalse(); }); }
public void Start( AsyncPassiveStateMachine <int, int> machine, bool entryActionExecuted, CurrentStateExtension currentStateExtension) { "establish an initialized state machine".x(() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .In(TestState) .ExecuteOnEntry(() => entryActionExecuted = true); machine = stateMachineDefinitionBuilder .WithInitialState(TestState) .Build() .CreatePassiveStateMachine(); currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); }); "when starting the state machine".x(() => machine.Start()); "should set current state of state machine to state to which it is initialized".x(() => currentStateExtension.CurrentState.Should().Be(TestState)); "should execute entry action of state to which state machine is initialized".x(() => entryActionExecuted.Should().BeTrue()); }
public void EntryAction( AsyncPassiveStateMachine <int, int> machine, bool entryActionExecuted, bool asyncEntryActionExecuted) { "establish a state machine with entry action on a state".x(() => { machine = new AsyncPassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnEntry(() => entryActionExecuted = true) .ExecuteOnEntry(async() => { asyncEntryActionExecuted = true; await Task.Yield(); }); }); "when entering the state".x(async() => { await machine.Initialize(State); await machine.Start(); }); "it should execute the synchronous entry action".x(() => entryActionExecuted.Should().BeTrue()); "it should execute the asynchronous entry action".x(() => asyncEntryActionExecuted.Should().BeTrue()); }
public void InitializeALoadedStateMachine( AsyncPassiveStateMachine <int, int> machine, Exception receivedException) { "establish a loaded initialized state machine".x(async() => { machine = new AsyncPassiveStateMachine <int, int>(); var loader = new Persisting.StateMachineLoader <int>(); loader.SetCurrentState(new Initializable <int> { Value = 1 }); loader.SetHistoryStates(new Dictionary <int, int>()); await machine.Load(loader); }); "when initializing the state machine".x(async() => receivedException = await Catch.Exception(async() => await machine.Initialize(0))); "should throw an invalid operation exception".x(() => { receivedException .Should().BeAssignableTo <InvalidOperationException>(); receivedException.Message .Should().Be(ExceptionMessages.StateMachineIsAlreadyInitialized); }); }
public void ExitActionException(AsyncPassiveStateMachine <int, int> machine) { "establish an exit action throwing an exception".x(() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .In(Values.Source) .ExecuteOnExit(() => throw Values.Exception) .On(Values.Event).Goto(Values.Destination); machine = stateMachineDefinitionBuilder .WithInitialState(Values.Source) .Build() .CreatePassiveStateMachine(); machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e; }); "when executing the transition".x(async() => { await machine.Start(); await machine.Fire(Values.Event, Values.Parameter); }); this.ItShouldHandleTransitionException(); }
public void NoExceptionHandlerRegistered( AsyncPassiveStateMachine <int, int> machine, Exception catchedException) { "establish an exception throwing state machine without a registered exception handler".x(async() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .In(Values.Source) .On(Values.Event).Execute(() => throw Values.Exception); machine = stateMachineDefinitionBuilder .WithInitialState(Values.Source) .Build() .CreatePassiveStateMachine(); await machine.Start(); }); "when an exception occurs".x(async() => catchedException = await Catch.Exception(async() => await machine.Fire(Values.Event))); "should (re-)throw exception".x(() => catchedException.InnerException .Should().BeSameAs(Values.Exception)); }
public void StartingException(AsyncPassiveStateMachine <int, int> machine) { const int state = 1; "establish a entry action for the initial state that throws an exception".x(() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .In(state) .ExecuteOnEntry(() => throw Values.Exception); machine = stateMachineDefinitionBuilder .WithInitialState(Values.Source) .Build() .CreatePassiveStateMachine(); machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e; }); "when starting the state machine".x(async() => { await machine.Start(); }); "should catch exception and fire transition exception event".x(() => this.receivedTransitionExceptionEventArgs.Exception.Should().NotBeNull()); "should pass thrown exception to event arguments of transition exception event".x(() => this.receivedTransitionExceptionEventArgs.Exception.Should().BeSameAs(Values.Exception)); }
public void NoMatchingGuard( AsyncPassiveStateMachine <int, int> machine) { bool declined = false; "establish state machine with no matching guard".x(async() => { machine = new AsyncPassiveStateMachine <int, int>(); var currentStateExtension = new CurrentStateExtension(); machine.AddExtension(currentStateExtension); machine.In(SourceState) .On(Event) .If(() => Task.FromResult(false)).Goto(ErrorState); machine.TransitionDeclined += (sender, e) => declined = true; await machine.Initialize(SourceState); await machine.Start(); }); "when an event is fired".x(() => machine.Fire(Event)); "it should notify about declined transition".x(() => declined.Should().BeTrue("TransitionDeclined event should be fired")); }
public void ExceptionHandling( AsyncPassiveStateMachine <int, int> machine, bool exitAction1Executed, bool exitAction2Executed, bool exitAction3Executed, bool exitAction4Executed) { var exception2 = new Exception(); var exception3 = new Exception(); var exception4 = new Exception(); var receivedException = new List <Exception>(); "establish a state machine with several exit actions on a state and some of them throw an exception".x(() => { machine = new AsyncPassiveStateMachine <int, int>(); machine.In(State) .ExecuteOnExit(() => exitAction1Executed = true) .ExecuteOnExit(() => { exitAction2Executed = true; throw exception2; }) .ExecuteOnExit(() => { exitAction3Executed = true; throw exception3; }) .ExecuteOnExit(async() => { exitAction4Executed = true; await Task.Yield(); throw exception4; }) .On(Event).Goto(AnotherState); machine.TransitionExceptionThrown += (s, e) => receivedException.Add(e.Exception); }); "when entering the state".x(async() => { await machine.Initialize(State); await machine.Start(); await machine.Fire(Event); }); "it should execute all entry actions on entry".x(() => new[] { exitAction1Executed, exitAction2Executed, exitAction3Executed, exitAction4Executed }.Should().Equal(true, true, true, true)); "it should handle all exceptions of all throwing entry actions by firing the TransitionExceptionThrown event".x(() => receivedException .Should().BeEquivalentTo(exception2, exception3, exception4)); }
public void CommonAncestor( AsyncPassiveStateMachine <int, int> machine) { const int commonAncestorState = 0; const int sourceState = 1; const int parentOfSourceState = 2; const int siblingOfSourceState = 3; const int destinationState = 4; const int parentOfDestinationState = 5; const int siblingOfDestinationState = 6; const int Event = 0; var commonAncestorStateLeft = false; "establish a hierarchical state machine".x(async() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .DefineHierarchyOn(commonAncestorState) .WithHistoryType(HistoryType.None) .WithInitialSubState(parentOfSourceState) .WithSubState(parentOfDestinationState); stateMachineDefinitionBuilder .DefineHierarchyOn(parentOfSourceState) .WithHistoryType(HistoryType.None) .WithInitialSubState(sourceState) .WithSubState(siblingOfSourceState); stateMachineDefinitionBuilder .DefineHierarchyOn(parentOfDestinationState) .WithHistoryType(HistoryType.None) .WithInitialSubState(destinationState) .WithSubState(siblingOfDestinationState); stateMachineDefinitionBuilder .In(sourceState) .On(Event).Goto(destinationState); stateMachineDefinitionBuilder .In(commonAncestorState) .ExecuteOnExit(() => commonAncestorStateLeft = true); machine = stateMachineDefinitionBuilder .WithInitialState(sourceState) .Build() .CreatePassiveStateMachine(); await machine.Start(); }); "when firing an event resulting in a transition with a common ancestor".x(() => machine.Fire(Event)); "the state machine should remain inside common ancestor state".x(() => commonAncestorStateLeft .Should().BeFalse()); }
public void Background() { this.receivedTransitionExceptionEventArgs = null; this.machine = new AsyncPassiveStateMachine <int, int>(); this.machine.TransitionExceptionThrown += (s, e) => this.receivedTransitionExceptionEventArgs = e; }
public void ExceptionHandling( AsyncPassiveStateMachine <int, int> machine, bool entryAction1Executed, bool entryAction2Executed, bool entryAction3Executed, bool entryAction4Executed) { var exception2 = new Exception(); var exception3 = new Exception(); var exception4 = new Exception(); var receivedException = new List <Exception>(); "establish a state machine with several entry actions on a state and some of them throw an exception".x(() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .In(State) .ExecuteOnEntry(() => entryAction1Executed = true) .ExecuteOnEntry(() => { entryAction2Executed = true; throw exception2; }) .ExecuteOnEntry(() => { entryAction3Executed = true; throw exception3; }) .ExecuteOnEntry(async() => { entryAction4Executed = true; await Task.Yield(); throw exception4; }); machine = stateMachineDefinitionBuilder .WithInitialState(State) .Build() .CreatePassiveStateMachine(); machine.TransitionExceptionThrown += (s, e) => receivedException.Add(e.Exception); }); "when entering the state".x(async() => await machine.Start()); "it should execute all entry actions on entry".x(() => new[] { entryAction1Executed, entryAction2Executed, entryAction3Executed, entryAction4Executed }.Should().Equal(true, true, true, true)); "it should handle all exceptions of all throwing entry actions by firing the TransitionExceptionThrown event".x(() => receivedException .Should().BeEquivalentTo(exception2, exception3, exception4)); }
public void SavingEventsForPassiveStateMachine( AsyncPassiveStateMachine <string, int> machine, StateMachineSaver <string, int> saver) { "establish a state machine".x(() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, int>(); stateMachineDefinitionBuilder .In("A") .On(1) .Goto("B"); stateMachineDefinitionBuilder .In("B") .On(2) .Goto("C"); stateMachineDefinitionBuilder .In("C") .On(3) .Goto("A"); machine = stateMachineDefinitionBuilder .WithInitialState("A") .Build() .CreatePassiveStateMachine(); }); "when events are fired".x(async() => { await machine.Fire(1); await machine.Fire(2); await machine.FirePriority(3); await machine.FirePriority(4); }); "and it is saved".x(async() => { saver = new StateMachineSaver <string, int>(); await machine.Save(saver); }); "it should save those events".x(() => { saver .Events .Select(x => x.EventId) .Should() .HaveCount(2) .And .ContainInOrder(1, 2); saver .PriorityEvents .Select(x => x.EventId) .Should() .HaveCount(2) .And .ContainInOrder(4, 3); }); }
public void Loading( StateMachineSaver <State> saver, StateMachineLoader <State> loader, FakeExtension extension, State sourceState, State targetState) { "establish a saved state machine with history"._(async() => { var machine = new AsyncPassiveStateMachine <State, Event>(); DefineMachine(machine); await machine.Initialize(State.A); await machine.Start(); await machine.Fire(Event.S2); // set history of super state S await machine.Fire(Event.B); // set current state to B saver = new StateMachineSaver <State>(); loader = new StateMachineLoader <State>(); await machine.Save(saver); }); "when state machine is loaded"._(async() => { loader.SetCurrentState(saver.CurrentStateId); loader.SetHistoryStates(saver.HistoryStates); extension = new FakeExtension(); var loadedMachine = new AsyncPassiveStateMachine <State, Event>(); loadedMachine.AddExtension(extension); DefineMachine(loadedMachine); await loadedMachine.Load(loader); loadedMachine.TransitionCompleted += (sender, args) => { sourceState = args.StateId; targetState = args.NewStateId; }; await loadedMachine.Start(); await loadedMachine.Fire(Event.S); }); "it should reset current state"._(() => sourceState.Should().Be(State.B)); "it should reset all history states of super states"._(() => targetState.Should().Be(State.S2)); "it should notify extensions"._(() => extension.LoadedCurrentState .Should().BeEquivalentTo(State.B)); }
public SubmissionStateMachine(Enrollee enrollee, SubmissionService submissionService) { _enrollee = enrollee; _submissionService = submissionService; var stateMachineBuilder = InitBuilder(); stateMachineBuilder.WithInitialState(FromEnrollee(enrollee)); _machine = stateMachineBuilder.Build().CreatePassiveStateMachine(); _machine.TransitionDeclined += (sender, e) => { throw new InvalidActionException(); }; _machine.Start(); }
public void CustomFactory( StandardFactory <string, int> factory) { "establish a custom factory".x(() => factory = A.Fake <StandardFactory <string, int> >()); "when creating a passive state machine".x(() => { var machine = new AsyncPassiveStateMachine <string, int>("_", factory); machine.In("initial").On(42).Goto("answer"); }); "it should use custom factory to create internal instances".x(() => A.CallTo(factory).MustHaveHappened()); }
public void DefaultStateMachineName( AsyncPassiveStateMachine <string, int> machine, StateMachineNameReporter reporter) { "establish an instantiated passive state machine".x(() => machine = new AsyncPassiveStateMachine <string, int>()); "establish a state machine reporter".x(() => reporter = new StateMachineNameReporter()); "when the state machine report is generated".x(() => machine.Report(reporter)); "it should use the type of the state machine as name for state machine".x(() => reporter.StateMachineName .Should().Be("Appccelerate.StateMachine.AsyncPassiveStateMachine<System.String,System.Int32>")); }
public void Report( IAsyncStateMachine <string, int> machine, IStateMachineReport <string, int> report) { "establish a state machine"._(() => machine = new AsyncPassiveStateMachine <string, int>()); "establish a state machine reporter"._(() => report = A.Fake <IStateMachineReport <string, int> >()); "when creating a report"._(() => machine.Report(report)); "it should call the passed reporter"._(() => A.CallTo(() => report.Report(A <string> ._, A <IEnumerable <IState <string, int> > > ._, A <Initializable <string> > ._)) .MustHaveHappened()); }
public void MultipleExitActions( AsyncPassiveStateMachine <int, int> machine, bool exitAction1Executed, bool exitAction2Executed, bool asyncExitAction1Executed, bool asyncExitAction2Executed) { "establish a state machine with several exit actions on a state".x(() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .In(State) .ExecuteOnExit(() => exitAction1Executed = true) .ExecuteOnExit(() => exitAction2Executed = true) .ExecuteOnExit(async() => { asyncExitAction1Executed = true; await Task.Yield(); }) .ExecuteOnExit(async() => { asyncExitAction2Executed = true; await Task.Yield(); }) .On(Event).Goto(AnotherState); machine = stateMachineDefinitionBuilder .WithInitialState(State) .Build() .CreatePassiveStateMachine(); }); "when leaving the state".x(async() => { await machine.Start(); await machine.Fire(Event); }); "it should execute all exit actions".x(() => new[] { exitAction1Executed, exitAction2Executed, asyncExitAction1Executed, asyncExitAction2Executed }.Should().Equal(true, true, true, true)); }
public void ExitActionWithParameter( AsyncPassiveStateMachine <int, int> machine, string receivedParameter, string asyncReceivedParameter) { const string parameter = "parameter"; "establish a state machine with exit action with parameter on a state".x(() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <int, int>(); stateMachineDefinitionBuilder .In(State) .ExecuteOnExitParametrized(p => receivedParameter = p, parameter) .ExecuteOnExitParametrized( async p => { asyncReceivedParameter = p; await Task.Yield(); }, parameter) .On(Event).Goto(AnotherState); machine = stateMachineDefinitionBuilder .WithInitialState(State) .Build() .CreatePassiveStateMachine(); }); "when leaving the state".x(async() => { await machine.Start(); await machine.Fire(Event); }); "it should execute the synchronous exit action".x(() => receivedParameter.Should().NotBeNull()); "it should pass parameter to the synchronous exit action".x(() => receivedParameter.Should().Be(parameter)); "it should execute the asynchronous exit action".x(() => asyncReceivedParameter.Should().NotBeNull()); "it should pass parameter to the asynchronous exit action".x(() => asyncReceivedParameter.Should().Be(parameter)); }
public void BeforeExecutingEntryActionsHierarchical( AsyncPassiveStateMachine <string, string> machine, IExtension <string, string> extension) { "establish an extension".x(() => extension = A.Fake <IExtension <string, string> >()); "establish a hierarchical state machine using the extension".x(async() => { var stateMachineDefinitionBuilder = new StateMachineDefinitionBuilder <string, string>(); stateMachineDefinitionBuilder .DefineHierarchyOn("A") .WithHistoryType(HistoryType.None) .WithInitialSubState("A0"); stateMachineDefinitionBuilder .In("0") .On("A0") .Goto("A0"); machine = stateMachineDefinitionBuilder .WithInitialState("0") .Build() .CreatePassiveStateMachine(Name); machine.AddExtension(extension); await machine.Start(); }); "when firing an event onto the state machine".x(() => machine.Fire("A0")); "it should call EnteringState on registered extensions for entered super states of target state".x(() => A.CallTo(() => extension.EnteringState( A <IStateMachineInformation <string, string> > .That.Matches(x => x.Name == Name && x.CurrentStateId.ExtractOrThrow() == "A0"), A <IStateDefinition <string, string> > .That.Matches(x => x.Id == "A"), A <ITransitionContext <string, string> > .That.Matches(x => x.EventId.Value == "A0"))) .MustHaveHappened()); "it should call EnteringState on registered extensions for entered leaf target state".x(() => A.CallTo(() => extension.EnteringState( A <IStateMachineInformation <string, string> > .That.Matches(x => x.Name == Name && x.CurrentStateId.ExtractOrThrow() == "A0"), A <IStateDefinition <string, string> > .That.Matches(x => x.Id == "A0"), A <ITransitionContext <string, string> > .That.Matches(x => x.EventId.Value == "A0"))) .MustHaveHappened()); }