public async Task ExecuteAsync_doesnt_execute_if_already_cancelled()
        {
            var sut = new StateTransitionDynamicAsync <Sale, SaleState, SaleEvent>(
                stateAccessor: sale => sale.State
                , stateMutator: (sale, newState) => sale.State = newState
                , stateFuncAsync: (sale, cancelToken) => Task.FromResult(SaleState.Complete)
                , name: "test"
                , priority: 1);

            using (var cancellationSource = new CancellationTokenSource())
            {
                cancellationSource.Cancel();
                var sale = new Sale(saleID: 87)
                {
                    State = SaleState.Open
                };
                var parameters = new ExecutionParameters <Sale, SaleEvent>(SaleEvent.Pay, sale, cancellationToken: cancellationSource.Token);

                var result = await sut.ExecuteAsync(parameters);

                Assert.True(result.WasCancelled);
                Assert.Equal(SaleState.Open, sale.State);
                Assert.Equal(SaleState.Open, result.CurrentState);
            }
        }
        public async Task ExecuteAsync_treats_lack_of_transitions_as_failed_condition()
        {
            var sut = new StateTransitionDynamicAsync <Sale, SaleState, SaleEvent>(
                stateAccessor: sale => sale.State
                , stateMutator: (sale, newState) => sale.State = newState
                , stateFuncAsync: (sale, cancelToken) => Task.FromResult(SaleState.Open)
                , name: "test"
                , priority: 1);

            using (var cancellationSource = new CancellationTokenSource())
            {
                var sale = new Sale(saleID: 87)
                {
                    State = SaleState.Open
                };
                var parameters = new ExecutionParameters <Sale, SaleEvent>(SaleEvent.Pay, sale, cancellationToken: cancellationSource.Token);

                var result = await sut.ExecuteAsync(parameters);

                Assert.False(result.ConditionMet);
                Assert.False(result.WasTransitioned);
                Assert.False(result.WasCancelled);
                Assert.Equal(SaleState.Open, sale.State);
                Assert.Equal(SaleState.Open, result.CurrentState);
                Assert.Equal(SaleState.Open, result.PreviousState);
            }
        }
        public async Task ExecuteAsync_doesnt_send_notification_if_no_state_change()
        {
            var sut = new StateTransitionDynamicAsync <Sale, SaleState, SaleEvent>(
                stateAccessor: sale => sale.State
                , stateMutator: (sale, newState) => sale.State = newState
                , stateFuncAsync: (sale, cancelToken) => Task.FromResult(SaleState.Open)
                , name: "test"
                , priority: 1);

            var notificationReceived = false;

            StateTransitionDynamicAsync <Sale, SaleState, SaleEvent> .OnTransitionedEvent += (sale, _) => notificationReceived = true;

            using (var cancellationSource = new CancellationTokenSource())
            {
                var sale = new Sale(saleID: 87)
                {
                    State = SaleState.Open
                };

                var parameters = new ExecutionParameters <Sale, SaleEvent>(SaleEvent.Pay, sale, cancellationToken: cancellationSource.Token);

                await sut.ExecuteAsync(parameters);

                Assert.False(notificationReceived);
            }
        }