public async Task WhenSuccessfullyAcquiresLease_AndProcessingCausesErrors_ItShouldLogErrors()
        {
            this.paymentProcessingLease.Setup(v => v.TryAcquireLeaseAsync()).ReturnsAsync(true).Verifiable();
            this.paymentProcessingLease.Setup(v => v.GetTimeSinceLastLeaseAsync()).ReturnsAsync(TimeSpan.MaxValue).Verifiable();
            this.paymentProcessingLease.Setup(v => v.GetIsAcquired()).Returns(true);

            var error1 = new PaymentProcessingException(new DivideByZeroException(), UserId.Random(), UserId.Random());
            var error2 = new PaymentProcessingException(new DivideByZeroException(), UserId.Random(), UserId.Random());

            this.processAllPayments.Setup(v => v.ExecuteAsync(this.paymentProcessingLease.Object, It.Is <List <PaymentProcessingException> >(l => l.Count == 0), CancellationToken))
            .Callback <IKeepAliveHandler, List <PaymentProcessingException>, CancellationToken>(
                (lease, errors, ct) =>
            {
                errors.Add(error1);
                errors.Add(error2);
            })
            .Returns(Task.FromResult(0)).Verifiable();

            this.requestProcessPayments.Setup(v => v.ExecuteAsync()).Returns(Task.FromResult(0)).Verifiable();
            this.paymentProcessingLease.Setup(v => v.UpdateTimestampsAsync()).Returns(Task.FromResult(0)).Verifiable();
            this.paymentProcessingLease.Setup(v => v.ReleaseLeaseAsync()).Returns(Task.FromResult(0)).Verifiable();

            this.logger.Setup(v => v.Error(error1)).Verifiable();
            this.logger.Setup(v => v.Error(error2)).Verifiable();

            await this.target.ProcessPaymentsAsync(new ProcessPaymentsMessage(), this.logger.Object, CancellationToken);

            this.paymentProcessingLease.Verify();
            this.requestProcessPayments.Verify();
            this.processAllPayments.Verify();

            this.logger.Verify();
        }
        public void GivenPaymentHandlerThrowsAPaymentProcessingException_WhenTryingToPostIt_ThenItReturnsABadRequestResponse()
        {
            // Given

            var mockedLogger         = Substitute.For <ILogger <PaymentProcessingController> >();
            var mockedPaymentHandler = Substitute.For <IPaymentHandler>();

            var realPaymentProcessingController = new PaymentProcessingController(mockedLogger, mockedPaymentHandler);

            var request = new PaymentProcessingRequest();

            var exception = new PaymentProcessingException("Test");

            mockedPaymentHandler
            .Handle(request)
            .Throws(exception);

            // When

            var response = realPaymentProcessingController.Post(request).GetAwaiter().GetResult();

            // Then

            response.Should().NotBeNull();
            response.Should().BeOfType <BadRequestObjectResult>();
            response.As <BadRequestObjectResult>().Value.As <PaymentProcessingFailedResponse>().Success.Should().BeFalse();
            response.As <BadRequestObjectResult>().Value.As <PaymentProcessingFailedResponse>().Message.Should().Be($"An error has occurred. Details: {exception.Message}");

            mockedPaymentHandler.Received(1).Handle(request);
        }