public void ExecuteAllRulesAsyncShouldReturnResultsForAllRules([Frozen] IExeucutesSingleRule ruleExecutor,
                                                                       SerialRuleExecutor sut,
                                                                       [ExecutableModel] ExecutableRuleAndDependencies rule1,
                                                                       [ExecutableModel] ExecutableRuleAndDependencies rule2,
                                                                       [ExecutableModel] ExecutableRuleAndDependencies rule3,
                                                                       IRuleExecutionContext executionContext,
                                                                       [RuleResult] ValidationRuleResult result1,
                                                                       [RuleResult] ValidationRuleResult result2,
                                                                       [RuleResult] ValidationRuleResult result3)
        {
            var allRules = new[] { rule1, rule2, rule3 };
            var sequence = new MockSequence();

            Mock.Get(executionContext).InSequence(sequence).Setup(x => x.GetRulesWhichMayBeExecuted()).Returns(() => allRules.Select(r => r.ExecutableRule));
            Mock.Get(executionContext).InSequence(sequence).Setup(x => x.GetRulesWhichMayBeExecuted()).Returns(() => Enumerable.Empty <ExecutableRule>());
            Mock.Get(ruleExecutor)
            .Setup(x => x.ExecuteRuleAsync(rule1.ExecutableRule, It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(result1));
            Mock.Get(ruleExecutor)
            .Setup(x => x.ExecuteRuleAsync(rule2.ExecutableRule, It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(result2));
            Mock.Get(ruleExecutor)
            .Setup(x => x.ExecuteRuleAsync(rule3.ExecutableRule, It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(result3));

            Assert.That(async() => await sut.ExecuteAllRulesAsync(executionContext, default),
                        Is.EquivalentTo(new[] { result1, result2, result3 }));
        }
        public async Task ExecuteAllRulesAsyncShouldUpdateTheResultUponTheRule([Frozen] IExeucutesSingleRule ruleExecutor,
                                                                               SerialRuleExecutor sut,
                                                                               [ExecutableModel] ExecutableRuleAndDependencies rule,
                                                                               IRuleExecutionContext executionContext,
                                                                               [RuleResult] ValidationRuleResult result)
        {
            var allRules = new[] { rule };
            var sequence = new MockSequence();

            Mock.Get(executionContext).InSequence(sequence).Setup(x => x.GetRulesWhichMayBeExecuted()).Returns(() => allRules.Select(r => r.ExecutableRule));
            Mock.Get(executionContext).InSequence(sequence).Setup(x => x.GetRulesWhichMayBeExecuted()).Returns(() => Enumerable.Empty <ExecutableRule>());
            Mock.Get(ruleExecutor)
            .Setup(x => x.ExecuteRuleAsync(rule.ExecutableRule, It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(result));

            await sut.ExecuteAllRulesAsync(executionContext);

            Assert.That(rule.ExecutableRule.Result, Is.SameAs(result));
        }
        public void ExecuteAllRulesAsyncShouldNotExecuteDependantRulesBeforeTheirDependenciesHaveResults([Frozen] IExeucutesSingleRule ruleExecutor,
                                                                                                         SerialRuleExecutor sut,
                                                                                                         [ExecutableModel] ExecutableRuleAndDependencies rule1,
                                                                                                         [ExecutableModel] ExecutableRuleAndDependencies rule2,
                                                                                                         [ExecutableModel] ExecutableRuleAndDependencies rule3,
                                                                                                         IRuleExecutionContext executionContext,
                                                                                                         [RuleResult] ValidationRuleResult result1,
                                                                                                         [RuleResult] ValidationRuleResult result2,
                                                                                                         [RuleResult] ValidationRuleResult result3)
        {
            var allRules = new[] { rule3, rule2, rule1 };

            Mock.Get(executionContext)
            .Setup(x => x.GetRulesWhichMayBeExecuted())
            .Returns(() =>
            {
                if (rule1.ExecutableRule.Result is null)
                {
                    return new[] { rule1.ExecutableRule }
                }
                ;
                if (rule2.ExecutableRule.Result is null)
                {
                    return new[] { rule2.ExecutableRule }
                }
                ;
                if (rule3.ExecutableRule.Result is null)
                {
                    return new[] { rule3.ExecutableRule }
                }
                ;
                return(Enumerable.Empty <ExecutableRule>());
            });
            Mock.Get(ruleExecutor)
            .Setup(x => x.ExecuteRuleAsync(rule1.ExecutableRule, It.IsAny <CancellationToken>()))
            .Returns(() => Task.FromResult(result1));
            Mock.Get(ruleExecutor)
            .Setup(x => x.ExecuteRuleAsync(rule2.ExecutableRule, It.IsAny <CancellationToken>()))
            .Callback(() =>
            {
                if (rule1.ExecutableRule.Result is null)
                {
                    Assert.Fail("Rule 2 should not be executed before rule 1");
                }
            })
            .Returns(() => Task.FromResult(result2));
            Mock.Get(ruleExecutor)
            .Setup(x => x.ExecuteRuleAsync(rule3.ExecutableRule, It.IsAny <CancellationToken>()))
            .Callback(() =>
            {
                if (rule1.ExecutableRule.Result is null || rule2.ExecutableRule.Result is null)
                {
                    Assert.Fail("Rule 3 should not be executed before rules 1 or 2");
                }
            })
            .Returns(() => Task.FromResult(result3));

            Assert.That(async() => await sut.ExecuteAllRulesAsync(executionContext, default),
                        Is.EquivalentTo(new[] { result1, result2, result3 }));
        }