public async Task DeveloperForgetsEndPrepare()
        {
            var exceptionCount = 0;
            var failureCount   = 0;
            var successCount   = 0;

            var profile = RetryLogic
                          .BeginPrepare()
                          .Handle <FileNotFoundException>()
                          .AtMost(10)
                          .WithConstantInterval(TimeSpan.FromMilliseconds(0))
                          .OnException <FileNotFoundException>(e => ++ exceptionCount)
                          .OnFailure(() => ++ failureCount);

            ////.EndPrepare(); // developer forgets tha line


            ////await RetryLogic.DoAsync(ActionThrowExceptionAsync, profile)
            try
            {
                await profile.DoAsync(ActionThrowExceptionAsync)
                .AtMost(5)
                .OnSuccess(x =>
                {
                    ++successCount;
                })
                .RunAsync();

                Assert.Fail("Should have thrown a InvalidOperationException");
            }
            catch (InvalidOperationException ex)
            {
                // ok
            }
        }
        public async Task ActionAsync_Should_Be_Tried_3Times_With_ConstantInterval()
        {
            var exceptionCount = 0;
            var failureCount   = 0;
            var successCount   = 0;
            var watch          = new Stopwatch();

            watch.Start();

            var profile = RetryLogic
                          .BeginPrepare()
                          .Handle <FileNotFoundException>()
                          .AtMost(3)
                          .WithConstantInterval(TimeSpan.FromMilliseconds(2000))
                          .WithTrace(true)
                          .OnException <FileNotFoundException>(e => ++ exceptionCount)
                          .OnFailure(() => ++ failureCount)
                          .EndPrepare();

            ////await RetryLogic.DoAsync(ActionThrowExceptionAsync, profile)
            await profile.DoAsync(ActionThrowExceptionAsync)
            .OnSuccess(x =>
            {
                ++successCount;
            })
            .RunAsync();

            watch.Stop();

            watch.Elapsed.ShouldBeGreaterThanOrEqualTo(TimeSpan.FromMilliseconds(2000 * 2));
            exceptionCount.ShouldEqual(3);
            failureCount.ShouldEqual(1);
            successCount.ShouldEqual(0);
        }
        public async Task ActionAsync_Should_Try_10_Times()
        {
            var exceptionCount = 0;
            var failureCount   = 0;
            var successCount   = 0;
            var watch          = new Stopwatch();

            watch.Start();

            var profile = RetryLogic
                          .BeginPrepare()
                          .Handle <FileNotFoundException>()
                          .AtMost(10)
                          .WithConstantInterval(TimeSpan.FromMilliseconds(0))
                          .OnException <FileNotFoundException>(e => ++ exceptionCount)
                          .OnFailure(() => ++ failureCount)
                          .EndPrepare();


            await profile.DoAsync(ActionThrowExceptionAsync)
            .OnSuccess(x =>
            {
                ++successCount;
            })
            .RunAsync();

            watch.Stop();
            exceptionCount.ShouldEqual(10);
            failureCount.ShouldEqual(1);
            successCount.ShouldEqual(0);
        }
        public async Task ActionAsync_Should_Throw_An_Exception()
        {
            var exceptionCount = 0;
            var failureCount   = 0;
            var successCount   = 0;
            var watch          = new Stopwatch();

            watch.Start();

            var profile = RetryLogic
                          .BeginPrepare()
                          .Handle <NullReferenceException>()
                          .AtMost(3)
                          .WithConstantInterval(TimeSpan.FromMilliseconds(2000))
                          .WithTrace(true)
                          .OnException <FileNotFoundException>(e => ++ exceptionCount)
                          .OnFailure(() => ++ failureCount)
                          .EndPrepare();

            try
            {
                ////await RetryLogic.DoAsync(ActionThrowExceptionAsync, profile)
                await profile.DoAsync(ActionThrowExceptionAsync)
                .OnSuccess(x =>
                {
                    ++successCount;
                })
                .RunAsync();
            }
            catch (Exception ex)
            {
                ex.ShouldBeType(typeof(FileNotFoundException));
            }
            watch.Stop();

            exceptionCount.ShouldEqual(0);
            failureCount.ShouldEqual(0);
            successCount.ShouldEqual(0);
        }