public void GivenAPaymentProcessingRequestIsProvided_WhenPostingToAcquirerBank_ThenItReturnsABankingResponse() { // Given var mockedAcquirerBankingService = Substitute.For <IAcquirerBankingService>(); var mockedLogger = Substitute.For <ILogger <BankingHandler> >(); var realBankingHandler = new BankingHandler(mockedLogger, mockedAcquirerBankingService); var request = new PaymentProcessingRequest(); mockedAcquirerBankingService .Post(request) .Returns(new BankingResponse { Success = true, TransactionId = Guid.NewGuid() }); // When var response = realBankingHandler.Handle(request).GetAwaiter().GetResult(); // Then response.Should().NotBeNull(); response.Should().BeOfType <BankingResponse>(); response.Success.Should().BeTrue(); }
public void GivenAcquirerBankingServiceThrowsAnException_WhenPostingToAcquirerBank_ThenItReturnsABankingException() { // Given var mockedAcquirerBankingService = Substitute.For <IAcquirerBankingService>(); var mockedLogger = Substitute.For <ILogger <BankingHandler> >(); var realBankingHandler = new BankingHandler(mockedLogger, mockedAcquirerBankingService); var request = new PaymentProcessingRequest(); var exception = new Exception("Exception thrown"); mockedAcquirerBankingService .Post(request) .Throws(exception); // When var response = Assert.Throws <BankingException>(() => realBankingHandler.Handle(request).GetAwaiter().GetResult()); // Then response.Should().NotBeNull(); response.Should().BeOfType <BankingException>(); response.Message.Should().Be(exception.Message); }
public void GivenAPaymentProcessingRequestIsProvided_WhenHandlingItAndTheBankingReturnsAFailedTransactionResponse_ThenItReturnsAFailedPaymentProcessingResponse() { // Given var mockedLogger = Substitute.For <ILogger <PaymentHandler> >(); var mockedBankingHandler = Substitute.For <IBankingHandler>(); var mockedPaymentRepository = Substitute.For <IPaymentRepository>(); var realPaymentHandler = new PaymentHandler(mockedLogger, mockedBankingHandler, mockedPaymentRepository); var request = new PaymentProcessingRequest(); mockedBankingHandler .Handle(request) .Returns(new BankingResponse { Success = false, TransactionId = Guid.NewGuid() }); // When var response = realPaymentHandler.Handle(request).GetAwaiter().GetResult(); // Then response.Should().NotBeNull(); response.Should().BeOfType <PaymentProcessingResponse>(); response.Success.Should().BeFalse(); mockedPaymentRepository.Received(2).Upsert(Arg.Any <PaymentRecord>()); mockedBankingHandler.Received(1).Handle(request); }
public async Task <IActionResult> Post([FromBody] PaymentProcessingRequest request) { if (!ModelState.IsValid) { return(BadRequest(ModelState)); } try { var result = await _paymentHandler.Handle(request); return(Ok(result)); } catch (PaymentProcessingException exception) { _logger.LogError(exception.ToString()); return(BadRequest(new PaymentProcessingFailedResponse { Success = false, Message = $"An error has occurred. Details: {exception.Message}" })); } catch (Exception exception) { _logger.LogError(exception.ToString()); return(BadRequest(new PaymentProcessingFailedResponse { Success = false, Message = $"An unhandled error has occurred. Details: {exception.Message}" })); } }
public void GivenABankingExceptionIsThrown_WhenHandlingIt_ThenItReturnsAPaymentProcessingException() { // Given var mockedLogger = Substitute.For <ILogger <PaymentHandler> >(); var mockedBankingHandler = Substitute.For <IBankingHandler>(); var mockedPaymentRepository = Substitute.For <IPaymentRepository>(); var realPaymentHandler = new PaymentHandler(mockedLogger, mockedBankingHandler, mockedPaymentRepository); var request = new PaymentProcessingRequest(); var exception = new BankingException("test"); mockedBankingHandler .Handle(request) .Throws(exception); // When var response = Assert.Throws <PaymentProcessingException>(() => realPaymentHandler.Handle(request).GetAwaiter().GetResult()); // Then response.Should().NotBeNull(); response.Should().BeOfType <PaymentProcessingException>(); response.Message.Should().Be($"There was an issue when processing the transaction with the bank. Details: {exception.Message}"); mockedPaymentRepository.Received(1).Upsert(Arg.Any <PaymentRecord>()); mockedBankingHandler.Received(1).Handle(request); }
public void GivenPaymentHandlerThrowsAnUnhandledException_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 Exception("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 unhandled error has occurred. Details: {exception.Message}"); mockedPaymentHandler.Received(1).Handle(request); }
private static bool AreFieldsEqual(PaymentRequest paymentRequest, PaymentProcessingRequest servicePaymentRequest) { return(paymentRequest.Number == servicePaymentRequest.Number && paymentRequest.Amount == servicePaymentRequest.Amount && paymentRequest.CVV == servicePaymentRequest.CVV && paymentRequest.Currency == servicePaymentRequest.Currency && paymentRequest.ExpiryMonth == servicePaymentRequest.ExpiryMonth && paymentRequest.ExpiryYear == servicePaymentRequest.ExpiryYear && paymentRequest.Name == servicePaymentRequest.Name); }
public async Task Process_AnyPaymentRequest_ReturnsSomeStatus() { // Arrange var paymentRequest = new PaymentProcessingRequest("Test", "1111111111111111", 12, 2025, 20, "EUR", 132); // Act var result = await _target.Process(paymentRequest); // Assert Assert.IsNotNull(result); Assert.IsFalse(string.IsNullOrEmpty(result.Status)); }
public async Task <BankingResponse> Handle(PaymentProcessingRequest paymentProcessingRequest) { try { var response = await _acquirerBankingService.Post(paymentProcessingRequest); return(response); } catch (Exception exception) { throw new BankingException(exception.Message); } }
public void GivenAPaymentProcessingRequestIsProvidedAndPaymentHandlerReturnsAFailedTransaction_WhenHandlingIt_ThenItReturnsAFailedResponse() { // Given var mockedLogger = Substitute.For <ILogger <PaymentProcessingController> >(); var mockedPaymentHandler = Substitute.For <IPaymentHandler>(); var realPaymentProcessingController = new PaymentProcessingController(mockedLogger, mockedPaymentHandler); const string cardNumber = "1234567812345678"; const int expiryMonth = 12; const int expiryYear = 2025; const int cvv = 123; const double amount = 123.45; const string currencyIsoCode = "GBP"; var request = new PaymentProcessingRequest { CardNumber = cardNumber, ExpiryMonth = expiryMonth, ExpiryYear = expiryYear, Cvv = cvv, Amount = amount, CurrencyIsoCode = currencyIsoCode }; var expectedId = Guid.NewGuid(); mockedPaymentHandler .Handle(request) .Returns(new PaymentProcessingResponse() { Success = false, PaymentGatewayId = expectedId }); // When var response = realPaymentProcessingController.Post(request).GetAwaiter().GetResult(); // Then response.Should().NotBeNull(); response.Should().BeOfType <OkObjectResult>(); response.As <OkObjectResult>().Value.Should().BeOfType <PaymentProcessingResponse>(); response.As <OkObjectResult>().Value.As <PaymentProcessingResponse>().Success.Should().BeFalse(); response.As <OkObjectResult>().Value.As <PaymentProcessingResponse>().PaymentGatewayId.Should().Be(expectedId); mockedPaymentHandler.Received(1).Handle(request); }
public static PaymentRecord Convert(PaymentProcessingRequest paymentProcessingRequest) { if (paymentProcessingRequest == null) { throw new ArgumentException("PaymentProcessingRequest cannot be null."); } return(new PaymentRecord { CardNumber = paymentProcessingRequest.CardNumber, ExpiryMonth = paymentProcessingRequest.ExpiryMonth, ExpiryYear = paymentProcessingRequest.ExpiryYear, Cvv = paymentProcessingRequest.Cvv, Amount = paymentProcessingRequest.Amount, CurrencyIsoCode = paymentProcessingRequest.CurrencyIsoCode, PaymentStatus = PaymentStatus.Pending, PaymentGatewayId = Guid.NewGuid() }); }
public async Task <PaymentProcessingResponse> Handle(PaymentProcessingRequest paymentProcessingRequest) { var paymentRecord = PaymentRecord.Convert(paymentProcessingRequest); try { await _paymentRepository.Upsert(paymentRecord); var bankResponse = await _bankHandler.Handle(paymentProcessingRequest); paymentRecord.BankTransactionId = bankResponse.TransactionId; paymentRecord.PaymentStatus = bankResponse.Success ? PaymentStatus.Success : PaymentStatus.Failed; await _paymentRepository.Upsert(paymentRecord); } catch (BankingException bankingException) { _logger.LogError(bankingException.ToString()); throw new PaymentProcessingException($"There was an issue when processing the transaction with the bank. Details: {bankingException.Message}"); } catch (PaymentRepositoryException paymentRepositoryException) { _logger.LogError(paymentRepositoryException.ToString()); throw new PaymentProcessingException($"There was an issue when saving the request. Details: {paymentRepositoryException.Message}"); } catch (Exception exception) { _logger.LogError(exception.ToString()); throw new PaymentProcessingException($"An unhandled error has occurred. Details: {exception.Message}"); } var response = new PaymentProcessingResponse { PaymentGatewayId = paymentRecord.PaymentGatewayId, Success = paymentRecord.PaymentStatus == PaymentStatus.Success }; return(response); }
public void GivenAValidPaymentProcessingRequest_WhenTryingToConvertToPaymentRecord_ThenItReturnsAPaymentRecord() { // Given const string cardNumber = "1234567812345678"; const int expiryMonth = 12; const int expiryYear = 2025; const int cvv = 123; const double amount = 123.45; const string currencyIsoCode = "GBP"; var request = new PaymentProcessingRequest { CardNumber = cardNumber, ExpiryMonth = expiryMonth, ExpiryYear = expiryYear, Cvv = cvv, Amount = amount, CurrencyIsoCode = currencyIsoCode }; // When var response = PaymentRecord.Convert(request); // Then response.Should().NotBeNull(); response.Should().BeOfType <PaymentRecord>(); response.CardNumber.Should().Be(cardNumber); response.ExpiryMonth.Should().Be(expiryMonth); response.ExpiryYear.Should().Be(expiryYear); response.Cvv.Should().Be(cvv); response.Amount.Should().Be(amount); response.CurrencyIsoCode.Should().Be(currencyIsoCode); response.PaymentStatus.Should().Be(PaymentStatus.Pending); response.PaymentGatewayId.Should().NotBe(Guid.Empty); }
public void GivenAValidPaymentRequest_WhenPostingId_ThenItReturnsASuccessfulResponse() { //Given var projectDir = GetProjectPath("", typeof(PaymentGatewayApiIntegrationTests).GetTypeInfo().Assembly); _ = new HostBuilder() .ConfigureWebHost(webHost => webHost .UseStartup(typeof(AcquiringBank.API.Fake.Startup)) .UseTestServer() .UseKestrel(options => options.Listen(IPAddress.Any, 51394))) .Start(); const string cardNumber = "1234567812345678"; const int expiryMonth = 12; const int expiryYear = 2025; const int cvv = 123; const double amount = 123.45; const string currencyIsoCode = "GBP"; var request = new PaymentProcessingRequest { CardNumber = cardNumber, ExpiryMonth = expiryMonth, ExpiryYear = expiryYear, Cvv = cvv, Amount = amount, CurrencyIsoCode = currencyIsoCode }; HttpContent httpRequest = new StringContent(JsonConvert.SerializeObject(request), Encoding.UTF8, "application/json"); ValidateAcquirerBankSuccessfulResponse(projectDir, httpRequest); ValidateAcquirerBankFailedResponse(projectDir, httpRequest); ValidateIfFailsWhenTryingToReachApiWithoutAuthorizationHeader(projectDir, httpRequest); }
public void GivenAnInvalidPaymentProcessingRequestIsProvided_WhenTryingToPostIt_ThenItReturnsABadRequestResponse() { // Given var mockedLogger = Substitute.For <ILogger <PaymentProcessingController> >(); var mockedPaymentHandler = Substitute.For <IPaymentHandler>(); var realPaymentProcessingController = new PaymentProcessingController(mockedLogger, mockedPaymentHandler); var request = new PaymentProcessingRequest(); realPaymentProcessingController.ModelState.AddModelError("CardNumber", "Error Message"); // When var response = realPaymentProcessingController.Post(request).GetAwaiter().GetResult(); // Then response.Should().NotBeNull(); response.Should().BeOfType <BadRequestObjectResult>(); mockedPaymentHandler.Received(0).Handle(request); }