Inheritance: ICircuit
        public void CheckThatFilteredxceptionsAreIgnored()
        {
            const string message = "testMessage";
            var exception = new Exception(message);
            var circuit = new Circuit<string>(1);
            circuit.ExceptionFilters.Add(e => e.Message == message);

            var circuit1 = circuit;
            Action execution = () => circuit1.Execute(() => { throw exception; });
            execution.ShouldThrow<Exception>().Where(e => e == exception);
            circuit.State.Position.Should().Be(CircuitPosition.Closed);
        }
        public void CheckThatExcludedExceptionsAreIgnored()
        {
            var exception = new NullReferenceException();
            var circuit = new Circuit<string>(1)
            {
                ExcludedExceptions = new[] { typeof(NullReferenceException) }
            };

            var circuit1 = circuit;
            Action execution = () => circuit1.Execute(() => { throw exception; });
            execution.ShouldThrow<NullReferenceException>().Where(e => e == exception);
            circuit.State.Position.Should().Be(CircuitPosition.Closed);
        }
        public void CheckThatTheCircuitFailsUntilTheCircuitIsHalfOpenAgainThenClosesAgainOnSuccess()
        {
            var timeSpan = TimeSpan.FromSeconds(1);
            bool[] throwException = { true };
            var failSafe = DateTime.UtcNow.Add(timeSpan.Add(timeSpan));
            var exception = new Exception();
            var circuit = new Circuit<string>(1, timeSpan);
            Func<string> function = () =>
            {
                if (throwException[0])
                {
                    throw exception;
                }

                return "success";
            };

            Action first = () => circuit.Execute(function);

            first.ShouldThrow<Exception>().Where(e => e == exception);
            circuit.State.Position.Should().Be(CircuitPosition.Open);

            while (DateTime.UtcNow < circuit.State.ResetTime)
            {
                Action action = () => circuit.Execute(function);

                action.ShouldThrow<CircuitOpenException>();

                failSafe.Should().BeAfter(DateTime.UtcNow, "otherwise the test has timed out");
            }

            circuit.State.Position.Should().Be(CircuitPosition.HalfOpen);

            throwException[0] = false;
            circuit.Execute(function);

            circuit.State.Position.Should().Be(CircuitPosition.Closed);
        }
        public void CircuitBreakerBreaksOnFailureAndSetsTheStateToOpenAfterTheThresholdIsReached()
        {
            var exception = new Exception();
            var circuit = new Circuit<string>(2);

            Action first = () => circuit.Execute(() => { throw exception; });
            first.ShouldThrow<Exception>().Where(e => e == exception);
            circuit.State.Position.Should().Be(CircuitPosition.Closed);

            Action second = () => circuit.Execute(() => { throw exception; });
            second.ShouldThrow<Exception>().Where(e => e == exception);
            circuit.State.Position.Should().Be(CircuitPosition.Open);
        }
        public void CheckThatTheThresholdIsResetAfterASuccessfulOperation()
        {
            var timeSpan = TimeSpan.FromSeconds(1);
            var failSafe = DateTime.UtcNow.Add(timeSpan.Add(timeSpan));
            bool[] throwException = { true };
            const int threshold = 2;
            var exception = new Exception();
            Func<string> function = () =>
            {
                if (throwException[0])
                {
                    throw exception;
                }

                return "success";
            };
            var circuit = new Circuit<string>(threshold, timeSpan);

            Action first = () => circuit.Execute(function);
            Action second = () => circuit.Execute(function);
            first.ShouldThrow<Exception>().Where(e => e == exception);
            second.ShouldThrow<Exception>().Where(e => e == exception);

            circuit.State.Position.Should().Be(CircuitPosition.Open);
            circuit.State.CurrentIteration.Should().Be(threshold);

            while (DateTime.UtcNow < circuit.State.ResetTime)
            {
                failSafe.Should().BeAfter(DateTime.UtcNow, "otherwise the test has timed out");
            }

            throwException[0] = false;
            circuit.Execute(function);

            circuit.State.Position.Should().Be(CircuitPosition.Closed);
            circuit.State.CurrentIteration.Should().Be(0);
        }
        public void CheckThatTheCircuitIsSetToHalfOpenAfterATimeout()
        {
            var timeSpan = TimeSpan.FromSeconds(1);
            var exception = new Exception();
            var circuit = new Circuit<string>(1, timeSpan);
            var failSafe = DateTime.UtcNow.Add(timeSpan.Add(timeSpan));

            circuit.State.Position.Should().Be(CircuitPosition.Closed);

            Action first = () => circuit.Execute(() => { throw exception; });
            first.ShouldThrow<Exception>().Where(e => e == exception);

            circuit.State.Position.Should().Be(CircuitPosition.Open);

            while (DateTime.UtcNow < circuit.State.ResetTime)
            {
                failSafe.Should().BeAfter(DateTime.UtcNow, "otherwise the test has timed out");
            }

            circuit.State.Position.Should().Be(CircuitPosition.HalfOpen);
        }
        public void CheckThatTheCircuitFailsUntilTheCircuitIsHalfOpenAgainThenOpensAgainOnFailure()
        {
            var timeSpan = TimeSpan.FromSeconds(1);
            var circuit = new Circuit<string>(1, timeSpan);
            var failSafe = DateTime.UtcNow.Add(timeSpan.Add(timeSpan));

            try
            {
                circuit.Execute(() => { throw new Exception(); });
            }
            catch
            {
                circuit.State.Position.Should().Be(CircuitPosition.Open);
            } 

            while (DateTime.UtcNow < circuit.State.ResetTime)
            {
                Action action = () => circuit.Execute(() => { throw new Exception(); });
                action.ShouldThrow<CircuitOpenException>();

                failSafe.Should().BeAfter(DateTime.UtcNow, "otherwise the test has timed out");
            }

            circuit.State.Position.Should().Be(CircuitPosition.HalfOpen);
            try
            {
                circuit.Execute(() => { throw new Exception(); });
            }
            catch
            {
                circuit.State.Position.Should().Be(CircuitPosition.Open);
            } 
        }