From a38bcdf1d33fd8ae24bb1d27e2c241243b740700 Mon Sep 17 00:00:00 2001 From: Stuart Ferguson Date: Thu, 29 May 2025 15:50:12 +0100 Subject: [PATCH] Refactor tests and improve error handling Updated test methods in `TransactionProcessorACLApplicationServiceTests.cs` to reflect new expected behaviors and renamed several test cases for clarity. Enhanced error handling in `TransactionProcessorACLApplicationService.cs` with more descriptive error messages and added an `ErrorMessages` property to response classes. Consolidated error response codes in `TestData.cs` and updated project files to include a `DebugType` property. Overall improvements made for better readability and maintainability of the tests. --- ...tionProcessorACLApplicationServiceTests.cs | 324 ++++++++++-------- ...ansactionProcessorACLApplicationService.cs | 202 +++-------- ...ionProcessorACL.DataTransferObjects.csproj | 1 + .../GetVoucherResponse.cs | 4 + .../ProcessLogonTransactionResponse.cs | 3 + .../ProcessReconciliationResponse.cs | 3 + .../ProcessSaleTransactionResponse.cs | 3 + .../RedeemVoucherResponse.cs | 4 + .../TransactionProcessorACL.Models.csproj | 1 + TransactionProcessorACL.Testing/TestData.cs | 93 ++++- 10 files changed, 331 insertions(+), 307 deletions(-) diff --git a/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs b/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs index 3067ac5..b57d3b6 100644 --- a/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs +++ b/TransactionProcessorACL.BusinessLogic.Tests/TransactionProcessorACLApplicationServiceTests.cs @@ -72,30 +72,41 @@ public async Task TransactionProcessorACLApplicationService_ProcessLogonTransact } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessLogonTransaction_InvalidOperationExceptionErrorInLogon_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessLogonTransaction_GetTokenFailed_ResultFailed() + { + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + Result result = await applicationService.ProcessLogonTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + CancellationToken.None); + + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task TransactionProcessorACLApplicationService_ProcessLogonTransaction_PerformTransactionFailed_ResultFailed() { - transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new InvalidOperationException(TestData.InvalidOperationErrorResponseMessage))); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); - + transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); Result result = await applicationService.ProcessLogonTransaction(TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - ProcessLogonTransactionResponse logonResponse = result.Data; - logonResponse.ShouldNotBeNull(); - logonResponse.ResponseMessage.ShouldBe(TestData.InvalidOperationErrorResponseMessage); - logonResponse.ResponseCode.ShouldBe(TestData.InvalidOperationErrorResponseCode); + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + CancellationToken.None); + + result.IsFailed.ShouldBeTrue(); } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessLogonTransaction_HttpRequestExceptionErrorInLogon_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessLogonTransaction_ExceptionErrorInLogon_TransactionIsNotSuccessful() { transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new HttpRequestException(TestData.HttpRequestErrorResponseMessage))); + .ThrowsAsync(new Exception("Error")); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); Result result = await applicationService.ProcessLogonTransaction(TestData.EstateId, @@ -107,31 +118,10 @@ public async Task TransactionProcessorACLApplicationService_ProcessLogonTransact result.IsSuccess.ShouldBeTrue(); ProcessLogonTransactionResponse logonResponse =result.Data; logonResponse.ShouldNotBeNull(); - logonResponse.ResponseMessage.ShouldContain(TestData.HttpRequestErrorResponseMessage); - logonResponse.ResponseCode.ShouldBe(TestData.HttpRequestErrorResponseCode); - } - - [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessLogonTransaction_OtherExceptionErrorInLogon_TransactionIsNotSuccessful() - { - transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new Exception(TestData.GeneralErrorResponseMessage))); - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); - - Result result = await applicationService.ProcessLogonTransaction(TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - ProcessLogonTransactionResponse logonResponse = result.Data; - - logonResponse.ShouldNotBeNull(); - logonResponse.ResponseMessage.ShouldBe(TestData.GeneralErrorResponseMessage); - logonResponse.ResponseCode.ShouldBe(TestData.GeneralErrorResponseCode); + logonResponse.ResponseMessage.ShouldContain(TestData.LogonExceptionResponseMessage); + logonResponse.ResponseCode.ShouldBe(TestData.ExceptionErrorResponseCode); } - + [Fact] public async Task TransactionProcessorACLApplicationService_ProcessSaleTransaction_TransactionIsSuccessful() { @@ -139,7 +129,7 @@ public async Task TransactionProcessorACLApplicationService_ProcessSaleTransacti .ReturnsAsync(TestData.SerialisedMessageResponseSale); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); - var result = await applicationService.ProcessSaleTransaction(TestData.EstateId, + Result result = await applicationService.ProcessSaleTransaction(TestData.EstateId, TestData.MerchantId, TestData.TransactionDateTime, TestData.TransactionNumber, @@ -159,64 +149,55 @@ public async Task TransactionProcessorACLApplicationService_ProcessSaleTransacti } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessSaleTransaction_InvalidOperationExceptionErrorInSale_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessSaleTransaction_GetTokenFailed_ResultFailed() { - transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new InvalidOperationException(TestData.InvalidOperationErrorResponseMessage))); - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); - var result = await applicationService.ProcessSaleTransaction(TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorId, - TestData.CustomerEmailAddress, - TestData.ContractId, - TestData.ProductId, - TestData.AdditionalRequestMetadata, - CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - ProcessSaleTransactionResponse saleResponse = result.Data; - saleResponse.ShouldNotBeNull(); - saleResponse.ResponseMessage.ShouldBe(TestData.InvalidOperationErrorResponseMessage); - saleResponse.ResponseCode.ShouldBe(TestData.InvalidOperationErrorResponseCode); + Result result = await applicationService.ProcessSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + TestData.OperatorId, + TestData.CustomerEmailAddress, + TestData.ContractId, + TestData.ProductId, + TestData.AdditionalRequestMetadata, + CancellationToken.None); + + result.IsFailed.ShouldBeTrue(); } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessSaleTransaction_HttpRequestExceptionErrorInSale_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessSaleTransaction_PerformTransactionFailed_ResultFailed() { transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new HttpRequestException(TestData.HttpRequestErrorResponseMessage))); + .ReturnsAsync(Result.Failure()); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); - var result = await applicationService.ProcessSaleTransaction(TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.TransactionNumber, - TestData.DeviceIdentifier, - TestData.OperatorId, - TestData.CustomerEmailAddress, - TestData.ContractId, - TestData.ProductId, - TestData.AdditionalRequestMetadata, - CancellationToken.None); + Result result = await applicationService.ProcessSaleTransaction(TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.TransactionNumber, + TestData.DeviceIdentifier, + TestData.OperatorId, + TestData.CustomerEmailAddress, + TestData.ContractId, + TestData.ProductId, + TestData.AdditionalRequestMetadata, + CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - ProcessSaleTransactionResponse saleResponse = result.Data; - saleResponse.ShouldNotBeNull(); - saleResponse.ResponseMessage.ShouldContain(TestData.HttpRequestErrorResponseMessage); - saleResponse.ResponseCode.ShouldBe(TestData.HttpRequestErrorResponseCode); + result.IsFailed.ShouldBeTrue(); } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessSaleTransaction_OtherExceptionErrorInSale_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessSaleTransaction_ExceptionErrorInSale_TransactionIsNotSuccessful() { transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new Exception(TestData.GeneralErrorResponseMessage))); + .ThrowsAsync(new Exception("Error")); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); - var result = await applicationService.ProcessSaleTransaction(TestData.EstateId, + Result result = await applicationService.ProcessSaleTransaction(TestData.EstateId, TestData.MerchantId, TestData.TransactionDateTime, TestData.TransactionNumber, @@ -227,12 +208,11 @@ public async Task TransactionProcessorACLApplicationService_ProcessSaleTransacti TestData.ProductId, TestData.AdditionalRequestMetadata, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); ProcessSaleTransactionResponse saleResponse = result.Data; saleResponse.ShouldNotBeNull(); - saleResponse.ResponseMessage.ShouldBe(TestData.GeneralErrorResponseMessage); - saleResponse.ResponseCode.ShouldBe(TestData.GeneralErrorResponseCode); + saleResponse.ResponseMessage.ShouldBe(TestData.SaleExceptionResponseMessage); + saleResponse.ResponseCode.ShouldBe(TestData.ExceptionErrorResponseCode); } [Fact] @@ -258,13 +238,11 @@ public async Task TransactionProcessorACLApplicationService_ProcessReconciliatio } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessReconciliation_InvalidOperationExceptionErrorInReconciliation_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessReconciliation_GetTokenFailed_ResultFailed() { - transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new InvalidOperationException(TestData.InvalidOperationErrorResponseMessage))); - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); - Result result= await applicationService.ProcessReconciliation(TestData.EstateId, + Result result = await applicationService.ProcessReconciliation(TestData.EstateId, TestData.MerchantId, TestData.TransactionDateTime, TestData.DeviceIdentifier, @@ -272,19 +250,15 @@ public async Task TransactionProcessorACLApplicationService_ProcessReconciliatio TestData.ReconciliationTransactionValue, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - ProcessReconciliationResponse reconciliationResponse = result.Data; - reconciliationResponse.ShouldNotBeNull(); - reconciliationResponse.ResponseMessage.ShouldBe(TestData.InvalidOperationErrorResponseMessage); - reconciliationResponse.ResponseCode.ShouldBe(TestData.InvalidOperationErrorResponseCode); + result.IsFailed.ShouldBeTrue(); } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessReconciliation_HttpRequestExceptionErrorInReconciliation_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessReconciliation_PerformTransactionFailed_ResultFailed() { - transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new HttpRequestException(TestData.HttpRequestErrorResponseMessage))); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); Result result = await applicationService.ProcessReconciliation(TestData.EstateId, TestData.MerchantId, @@ -294,33 +268,29 @@ public async Task TransactionProcessorACLApplicationService_ProcessReconciliatio TestData.ReconciliationTransactionValue, CancellationToken.None); - result.IsSuccess.ShouldBeTrue(); - ProcessReconciliationResponse reconciliationResponse = result.Data; - reconciliationResponse.ShouldNotBeNull(); - reconciliationResponse.ResponseMessage.ShouldContain(TestData.HttpRequestErrorResponseMessage); - reconciliationResponse.ResponseCode.ShouldBe(TestData.HttpRequestErrorResponseCode); + result.IsFailed.ShouldBeTrue(); } [Fact] - public async Task TransactionProcessorACLApplicationService_ProcessReconciliation_OtherExceptionErrorInReconciliation_TransactionIsNotSuccessful() + public async Task TransactionProcessorACLApplicationService_ProcessReconciliation_ExceptionErrorInReconciliation_TransactionIsNotSuccessful() { transactionProcessorClient.Setup(t => t.PerformTransaction(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new Exception(TestData.GeneralErrorResponseMessage))); + .ThrowsAsync(new Exception("Error")); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); - Result result = await applicationService.ProcessReconciliation(TestData.EstateId, - TestData.MerchantId, - TestData.TransactionDateTime, - TestData.DeviceIdentifier, - TestData.ReconciliationTransactionCount, - TestData.ReconciliationTransactionValue, - CancellationToken.None); + Result result= await applicationService.ProcessReconciliation(TestData.EstateId, + TestData.MerchantId, + TestData.TransactionDateTime, + TestData.DeviceIdentifier, + TestData.ReconciliationTransactionCount, + TestData.ReconciliationTransactionValue, + CancellationToken.None); result.IsSuccess.ShouldBeTrue(); ProcessReconciliationResponse reconciliationResponse = result.Data; reconciliationResponse.ShouldNotBeNull(); - reconciliationResponse.ResponseMessage.ShouldBe(TestData.GeneralErrorResponseMessage); - reconciliationResponse.ResponseCode.ShouldBe(TestData.GeneralErrorResponseCode); + reconciliationResponse.ResponseMessage.ShouldBe(TestData.ReconciliationExceptionResponseMessage); + reconciliationResponse.ResponseCode.ShouldBe(TestData.ExceptionErrorResponseCode); } [Fact] @@ -342,45 +312,41 @@ public async Task VoucherManagementACLApplicationService_GetVoucher_VoucherRetri } [Fact] - public async Task VoucherManagementACLApplicationService_GetVoucher_InvalidOperationExceptionErrorInGetVoucher_GetVoucherIsNotSuccessful() + public async Task VoucherManagementACLApplicationService_GetVoucher_GetTokenFailed_ResultIsFailed() { - transactionProcessorClient.Setup(v => v.GetVoucherByCode(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new InvalidOperationException(TestData.InvalidOperationErrorResponseMessage))); - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); GetVoucherResponse voucherResponse = await applicationService.GetVoucher(TestData.EstateId, TestData.ContractId, TestData.VoucherCode, CancellationToken.None); voucherResponse.ShouldNotBeNull(); - voucherResponse.ResponseMessage.ShouldBe(TestData.InvalidOperationErrorResponseMessage); - voucherResponse.ResponseCode.ShouldBe(TestData.InvalidOperationErrorResponseCode); + voucherResponse.ResponseCode.ShouldBe("0004"); } [Fact] - public async Task VoucherManagementACLApplicationService_GetVoucher_HttpRequestExceptionErrorInGetVoucher_GetVoucherNotSuccessful() + public async Task VoucherManagementACLApplicationService_GetVoucher_GetVoucherFailed_ResultIsFailed() { - transactionProcessorClient.Setup(v => v.GetVoucherByCode(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new HttpRequestException(TestData.HttpRequestErrorResponseMessage))); + this.transactionProcessorClient.Setup(v => v.GetVoucherByCode(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); GetVoucherResponse voucherResponse = await applicationService.GetVoucher(TestData.EstateId, TestData.ContractId, TestData.VoucherCode, CancellationToken.None); voucherResponse.ShouldNotBeNull(); - voucherResponse.ResponseMessage.ShouldBe(TestData.HttpRequestErrorResponseMessage); - voucherResponse.ResponseCode.ShouldBe(TestData.HttpRequestErrorResponseCode); + voucherResponse.ResponseCode.ShouldBe("0005"); } [Fact] - public async Task VoucherManagementACLApplicationService_GetVoucher_OtherExceptionErrorInInGetVoucher_GetVoucherNotSuccessful() + public async Task VoucherManagementACLApplicationService_GetVoucher_ExceptionErrorInGetVoucher_GetVoucherIsNotSuccessful() { transactionProcessorClient.Setup(v => v.GetVoucherByCode(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new Exception(TestData.GeneralErrorResponseMessage))); + .ThrowsAsync(new Exception("Error")); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); GetVoucherResponse voucherResponse = await applicationService.GetVoucher(TestData.EstateId, TestData.ContractId, TestData.VoucherCode, CancellationToken.None); voucherResponse.ShouldNotBeNull(); - voucherResponse.ResponseMessage.ShouldBe(TestData.GeneralErrorResponseMessage); - voucherResponse.ResponseCode.ShouldBe(TestData.GeneralErrorResponseCode); + voucherResponse.ResponseMessage.ShouldBe(TestData.VoucherExceptionResponseMessage); + voucherResponse.ResponseCode.ShouldBe(TestData.ExceptionErrorResponseCode); } [Fact] @@ -401,46 +367,114 @@ public async Task VoucherManagementACLApplicationService_RedeemVoucher_VoucherRe } [Fact] - public async Task VoucherManagementACLApplicationService_RedeemVoucher_InvalidOperationExceptionErrorInGetVoucher_GetVoucherIsNotSuccessful() + public async Task VoucherManagementACLApplicationService_RedeemVoucher_GetTokenFailed_ResultIsFailed() { - transactionProcessorClient.Setup(v => v.RedeemVoucher(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new InvalidOperationException(TestData.InvalidOperationErrorResponseMessage))); - - securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + transactionProcessorClient.Setup(v => v.RedeemVoucher(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.RedeemVoucherResponse); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); RedeemVoucherResponse voucherResponse = await applicationService.RedeemVoucher(TestData.EstateId, TestData.ContractId, TestData.VoucherCode, CancellationToken.None); voucherResponse.ShouldNotBeNull(); - voucherResponse.ResponseMessage.ShouldBe(TestData.InvalidOperationErrorResponseMessage); - voucherResponse.ResponseCode.ShouldBe(TestData.InvalidOperationErrorResponseCode); + voucherResponse.ResponseCode.ShouldBe("0004"); } [Fact] - public async Task VoucherManagementACLApplicationService_RedeemVoucher_HttpRequestExceptionErrorInGetVoucher_GetVoucherNotSuccessful() + public async Task VoucherManagementACLApplicationService_RedeemVoucher_RedeemVoucherFailed_ResultIsFailed() { transactionProcessorClient.Setup(v => v.RedeemVoucher(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new HttpRequestException(TestData.HttpRequestErrorResponseMessage))); + .ReturnsAsync(Result.Failure()); securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); RedeemVoucherResponse voucherResponse = await applicationService.RedeemVoucher(TestData.EstateId, TestData.ContractId, TestData.VoucherCode, CancellationToken.None); voucherResponse.ShouldNotBeNull(); - voucherResponse.ResponseMessage.ShouldBe(TestData.HttpRequestErrorResponseMessage); - voucherResponse.ResponseCode.ShouldBe(TestData.HttpRequestErrorResponseCode); + voucherResponse.ResponseCode.ShouldBe("0005"); } [Fact] - public async Task VoucherManagementACLApplicationService_RedeemVoucher_OtherExceptionErrorInInGetVoucher_GetVoucherNotSuccessful() + public async Task VoucherManagementACLApplicationService_RedeemVoucher_ExceptionErrorInGetVoucher_GetVoucherIsNotSuccessful() { - transactionProcessorClient.Setup(v => v.RedeemVoucher(It.IsAny(), It.IsAny(), It.IsAny())) - .ThrowsAsync(new Exception("Error", new Exception(TestData.GeneralErrorResponseMessage))); + transactionProcessorClient.Setup(v => v.RedeemVoucher(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception("Error")); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); RedeemVoucherResponse voucherResponse = await applicationService.RedeemVoucher(TestData.EstateId, TestData.ContractId, TestData.VoucherCode, CancellationToken.None); voucherResponse.ShouldNotBeNull(); - voucherResponse.ResponseMessage.ShouldBe(TestData.GeneralErrorResponseMessage); - voucherResponse.ResponseCode.ShouldBe(TestData.GeneralErrorResponseCode); + voucherResponse.ResponseMessage.ShouldBe(TestData.RedeemVoucherExceptionResponseMessage); + voucherResponse.ResponseCode.ShouldBe(TestData.ExceptionErrorResponseCode); + } + + [Theory] + [InlineData(TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule.Immediate)] + [InlineData(TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule.Weekly)] + [InlineData(TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule.Monthly)] + public async Task VoucherManagementACLApplicationService_GetMerchant_MerchantReturned(TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule settlementSchedule) + { + transactionProcessorClient.Setup(v => v.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.MerchantResponse(settlementSchedule))); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + + Result merchantResponse = await applicationService.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + merchantResponse.IsSuccess.ShouldBeTrue(); + merchantResponse.Data.ShouldNotBeNull(); + merchantResponse.Data.MerchantId.ShouldBe(TestData.MerchantId); + } + + [Fact] + public async Task VoucherManagementACLApplicationService_GetMerchant_GetTokenFailed_ResultIsFailed() + { + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + Result merchantResponse = await applicationService.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + merchantResponse.IsFailed.ShouldBeTrue(); + + } + + [Fact] + public async Task VoucherManagementACLApplicationService_GetMerchant_GetMerchantFailed_ResultIsFailed() + { + transactionProcessorClient.Setup(v => v.GetMerchant(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + + Result merchantResponse = await applicationService.GetMerchant(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + merchantResponse.IsFailed.ShouldBeTrue(); + } + + [Theory] + [InlineData(TransactionProcessor.DataTransferObjects.Responses.Contract.ProductType.Voucher)] + [InlineData(TransactionProcessor.DataTransferObjects.Responses.Contract.ProductType.BillPayment)] + [InlineData(TransactionProcessor.DataTransferObjects.Responses.Contract.ProductType.MobileTopup)] + public async Task VoucherManagementACLApplicationService_GetMerchantContracts_MerchantContractsReturned(TransactionProcessor.DataTransferObjects.Responses.Contract.ProductType productType) { + transactionProcessorClient.Setup(v => v.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Success(TestData.MerchantContractResponses(productType))); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + + var merchantContractsResponse = await applicationService.GetMerchantContracts(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + merchantContractsResponse.IsSuccess.ShouldBeTrue(); + } + + [Fact] + public async Task VoucherManagementACLApplicationService_GetMerchantContracts_GetTokenFailed_ResultIsFailed() + { + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Failure()); + + var merchantContractsResponse = await applicationService.GetMerchantContracts(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + merchantContractsResponse.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task VoucherManagementACLApplicationService_GetMerchantContracts_GetMerchantContractsFailed_ResultIsFailed() + { + transactionProcessorClient.Setup(v => v.GetMerchantContracts(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + securityServiceClient.Setup(s => s.GetToken(It.IsAny(), It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success(TestData.TokenResponse)); + + var merchantContractsResponse = await applicationService.GetMerchantContracts(TestData.EstateId, TestData.MerchantId, CancellationToken.None); + merchantContractsResponse.IsFailed.ShouldBeTrue(); } } } diff --git a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs index ff8f0cf..457935e 100644 --- a/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs +++ b/TransactionProcessorACL.BusinessLogic/Services/TransactionProcessorACLApplicationService.cs @@ -1,4 +1,5 @@ -using Shared.Results; +using Shared.Exceptions; +using Shared.Results; using SimpleResults; using TransactionProcessor.DataTransferObjects.Responses.Contract; @@ -101,10 +102,8 @@ public async Task> ProcessLogonTransacti ProcessLogonTransactionResponse response = null; - try - { - Result transactionResult = - await this.TransactionProcessorClient.PerformTransaction(accessToken.AccessToken, requestSerialisedMessage, cancellationToken); + try { + Result transactionResult = await this.TransactionProcessorClient.PerformTransaction(accessToken.AccessToken, requestSerialisedMessage, cancellationToken); if (transactionResult.IsFailed) return ResultHelpers.CreateFailure(transactionResult); @@ -112,51 +111,22 @@ public async Task> ProcessLogonTransacti LogonTransactionResponse logonTransactionResponse = JsonConvert.DeserializeObject(responseSerialisedMessage.SerialisedData); - response = new ProcessLogonTransactionResponse - { - ResponseCode = logonTransactionResponse.ResponseCode, - ResponseMessage = logonTransactionResponse.ResponseMessage, - EstateId = estateId, - MerchantId = merchantId, - TransactionId = logonTransactionResponse.TransactionId, + response = new ProcessLogonTransactionResponse { + ResponseCode = logonTransactionResponse.ResponseCode, + ResponseMessage = logonTransactionResponse.ResponseMessage, + EstateId = estateId, + MerchantId = merchantId, + TransactionId = logonTransactionResponse.TransactionId, }; } - catch(Exception ex) - { - if (ex.InnerException is InvalidOperationException) - { - // This means there is an error in the request - response = new ProcessLogonTransactionResponse - { - ResponseCode = "0001", // Request Message error - ResponseMessage = ex.InnerException.Message, - EstateId = estateId, - MerchantId = merchantId - }; - } - else if (ex.InnerException is HttpRequestException) - { - Logger.LogError(ex.InnerException); - - // Request Send Exception - response = new ProcessLogonTransactionResponse - { - ResponseCode = "0002", // Request Message error - ResponseMessage = $"Error Sending Request Message [{ex.InnerException.Message}]", - EstateId = estateId, - MerchantId = merchantId - }; - } - else - { - response = new ProcessLogonTransactionResponse - { - ResponseCode = "0003", // General error - ResponseMessage = "General Error", - EstateId = estateId, - MerchantId = merchantId - }; - } + catch (Exception ex) { + response = new ProcessLogonTransactionResponse { + ResponseCode = "0001", // Request Message error + ResponseMessage = "Process Logon Failed", + EstateId = estateId, + MerchantId = merchantId, + ErrorMessages = ex.GetExceptionMessages() + }; } return Result.Success(response); @@ -249,38 +219,14 @@ public async Task> ProcessSaleTransaction } catch (Exception ex) { - if (ex.InnerException is InvalidOperationException) - { - // This means there is an error in the request - response = new ProcessSaleTransactionResponse - { - ResponseCode = "0001", // Request Message error - ResponseMessage = ex.InnerException.Message, - EstateId = estateId, - MerchantId = merchantId - }; - } - else if (ex.InnerException is HttpRequestException) - { - // Request Send Exception - response = new ProcessSaleTransactionResponse - { - ResponseCode = "0002", // Request Message error - ResponseMessage = "Error Sending Request Message", - EstateId = estateId, - MerchantId = merchantId - }; - } - else + response = new ProcessSaleTransactionResponse { - response = new ProcessSaleTransactionResponse - { - ResponseCode = "0003", // General error - ResponseMessage = "General Error", - EstateId = estateId, - MerchantId = merchantId - }; - } + ResponseCode = "0001", // Request Message error + ResponseMessage = "Process Sale Failed", + EstateId = estateId, + MerchantId = merchantId, + ErrorMessages = ex.GetExceptionMessages() + }; } return Result.Success(response); @@ -339,32 +285,14 @@ public async Task> ProcessReconciliation(G } catch (Exception ex) { - if (ex.InnerException is InvalidOperationException) - { - // This means there is an error in the request - response = new ProcessReconciliationResponse - { - ResponseCode = "0001", // Request Message error - ResponseMessage = ex.InnerException.Message - }; - } - else if (ex.InnerException is HttpRequestException) - { - // Request Send Exception - response = new ProcessReconciliationResponse - { - ResponseCode = "0002", // Request Message error - ResponseMessage = "Error Sending Request Message" - }; - } - else + response = new ProcessReconciliationResponse { - response = new ProcessReconciliationResponse - { - ResponseCode = "0003", // General error - ResponseMessage = "General Error" - }; - } + ResponseCode = "0001", // Request Message error + ResponseMessage = "Process Reconciliation Failed", + EstateId = estateId, + MerchantId = merchantId, + ErrorMessages = ex.GetExceptionMessages() + }; } return Result.Success(response); @@ -416,32 +344,13 @@ public async Task GetVoucher(Guid estateId, } catch (Exception ex) { - if (ex.InnerException is InvalidOperationException) - { - // This means there is an error in the request - response = new GetVoucherResponse - { - ResponseCode = "0001", // Request Message error - ResponseMessage = ex.InnerException.Message, - }; - } - else if (ex.InnerException is HttpRequestException) - { - // Request Send Exception - response = new GetVoucherResponse - { - ResponseCode = "0002", // Request Message error - ResponseMessage = "Error Sending Request Message", - }; - } - else + // This means there is an error in the request + response = new GetVoucherResponse { - response = new GetVoucherResponse - { - ResponseCode = "0003", // General error - ResponseMessage = "General Error", - }; - } + ResponseCode = "0001", // Request Message error + ResponseMessage = "Get Voucher Failed", + ErrorMessages = ex.GetExceptionMessages() + }; } return response; @@ -499,34 +408,15 @@ public async Task RedeemVoucher(Guid estateId, } catch (Exception ex) { - if (ex.InnerException is InvalidOperationException) - { - // This means there is an error in the request - response = new RedeemVoucherResponse - { - ResponseCode = "0001", // Request Message error - ResponseMessage = ex.InnerException.Message, - }; - } - else if (ex.InnerException is HttpRequestException) - { - // Request Send Exception - response = new RedeemVoucherResponse - { - ResponseCode = "0002", // Request Message error - ResponseMessage = "Error Sending Request Message", - }; - } - else + // This means there is an error in the request + response = new RedeemVoucherResponse { - response = new RedeemVoucherResponse - { - ResponseCode = "0003", // General error - ResponseMessage = "General Error", - }; - } + ResponseCode = "0001", // Request Message error + ResponseMessage = "Redeem Voucher Failed", + ErrorMessages = ex.GetExceptionMessages() + }; } - + return response; } @@ -540,7 +430,7 @@ public async Task RedeemVoucher(Guid estateId, Result accessTokenResult = await this.SecurityServiceClient.GetToken(clientId, clientSecret, cancellationToken); if (accessTokenResult.IsFailed) { - ResultHelpers.CreateFailure(accessTokenResult); + return ResultHelpers.CreateFailure(accessTokenResult); } TokenResponse accessToken = accessTokenResult.Data; diff --git a/TransactionProcessorACL.DataTransferObjects/TransactionProcessorACL.DataTransferObjects.csproj b/TransactionProcessorACL.DataTransferObjects/TransactionProcessorACL.DataTransferObjects.csproj index 234b4d7..93c8771 100644 --- a/TransactionProcessorACL.DataTransferObjects/TransactionProcessorACL.DataTransferObjects.csproj +++ b/TransactionProcessorACL.DataTransferObjects/TransactionProcessorACL.DataTransferObjects.csproj @@ -2,6 +2,7 @@ net8.0;netstandard2.1 + None diff --git a/TransactionProcessorACL.Models/GetVoucherResponse.cs b/TransactionProcessorACL.Models/GetVoucherResponse.cs index 2c8c044..e4bee87 100644 --- a/TransactionProcessorACL.Models/GetVoucherResponse.cs +++ b/TransactionProcessorACL.Models/GetVoucherResponse.cs @@ -1,6 +1,7 @@ namespace TransactionProcessorACL.Models; using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] @@ -26,5 +27,8 @@ public class GetVoucherResponse public Guid VoucherId { get; set; } + + public List ErrorMessages { get; set; } + #endregion } \ No newline at end of file diff --git a/TransactionProcessorACL.Models/ProcessLogonTransactionResponse.cs b/TransactionProcessorACL.Models/ProcessLogonTransactionResponse.cs index 95af78f..c089e72 100644 --- a/TransactionProcessorACL.Models/ProcessLogonTransactionResponse.cs +++ b/TransactionProcessorACL.Models/ProcessLogonTransactionResponse.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; namespace TransactionProcessorACL.Models { @@ -40,5 +41,7 @@ public class ProcessLogonTransactionResponse public Guid MerchantId { get; set; } public Guid TransactionId { get; set; } + + public List ErrorMessages { get; set; } } } diff --git a/TransactionProcessorACL.Models/ProcessReconciliationResponse.cs b/TransactionProcessorACL.Models/ProcessReconciliationResponse.cs index 9c61f5f..c75add1 100644 --- a/TransactionProcessorACL.Models/ProcessReconciliationResponse.cs +++ b/TransactionProcessorACL.Models/ProcessReconciliationResponse.cs @@ -2,6 +2,7 @@ namespace TransactionProcessorACL.Models { + using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] @@ -40,5 +41,7 @@ public class ProcessReconciliationResponse public Guid MerchantId { get; set; } public Guid TransactionId { get; set; } + + public List ErrorMessages { get; set; } } } diff --git a/TransactionProcessorACL.Models/ProcessSaleTransactionResponse.cs b/TransactionProcessorACL.Models/ProcessSaleTransactionResponse.cs index f7dc522..8cd0b59 100644 --- a/TransactionProcessorACL.Models/ProcessSaleTransactionResponse.cs +++ b/TransactionProcessorACL.Models/ProcessSaleTransactionResponse.cs @@ -18,5 +18,8 @@ public class ProcessSaleTransactionResponse public Dictionary AdditionalTransactionMetadata { get; set; } public Guid TransactionId { get; set; } + + public List ErrorMessages { get; set; } + } } \ No newline at end of file diff --git a/TransactionProcessorACL.Models/RedeemVoucherResponse.cs b/TransactionProcessorACL.Models/RedeemVoucherResponse.cs index 507c8a8..1670d01 100644 --- a/TransactionProcessorACL.Models/RedeemVoucherResponse.cs +++ b/TransactionProcessorACL.Models/RedeemVoucherResponse.cs @@ -1,6 +1,7 @@ namespace TransactionProcessorACL.Models; using System; +using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; [ExcludeFromCodeCoverage] @@ -22,5 +23,8 @@ public class RedeemVoucherResponse public String VoucherCode { get; set; } + + public List ErrorMessages { get; set; } + #endregion } \ No newline at end of file diff --git a/TransactionProcessorACL.Models/TransactionProcessorACL.Models.csproj b/TransactionProcessorACL.Models/TransactionProcessorACL.Models.csproj index 95ce5f9..1406d20 100644 --- a/TransactionProcessorACL.Models/TransactionProcessorACL.Models.csproj +++ b/TransactionProcessorACL.Models/TransactionProcessorACL.Models.csproj @@ -2,6 +2,7 @@ net8.0 + None diff --git a/TransactionProcessorACL.Testing/TestData.cs b/TransactionProcessorACL.Testing/TestData.cs index ebc86b0..8024e56 100644 --- a/TransactionProcessorACL.Testing/TestData.cs +++ b/TransactionProcessorACL.Testing/TestData.cs @@ -65,14 +65,14 @@ public class TestData TestData.DeviceIdentifier); public static String ResponseCode = "0000"; - public static String InvalidOperationErrorResponseCode = "0001"; - public static String HttpRequestErrorResponseCode = "0002"; - public static String GeneralErrorResponseCode = "0003"; + public static String ExceptionErrorResponseCode = "0001"; public static String ResponseMessage = "SUCCESS"; - public static String InvalidOperationErrorResponseMessage = "ERROR"; - public static String HttpRequestErrorResponseMessage = "Error Sending Request Message"; - public static String GeneralErrorResponseMessage = "General Error"; + public static String LogonExceptionResponseMessage = "Process Logon Failed"; + public static String SaleExceptionResponseMessage = "Process Sale Failed"; + public static String ReconciliationExceptionResponseMessage = "Process Reconciliation Failed"; + public static String VoucherExceptionResponseMessage = "Get Voucher Failed"; + public static String RedeemVoucherExceptionResponseMessage = "Redeem Voucher Failed"; public static ProcessLogonTransactionResponse ProcessLogonTransactionResponse = new ProcessLogonTransactionResponse { @@ -313,6 +313,87 @@ public class TestData public static DateTime RedeemedDateTime = new DateTime(); public static Guid TransactionId = Guid.Parse("793ACA88-B501-435E-BF08-1E5F639A7885"); + public static String MerchantName = "Test Merchant Name"; + public static Guid DeviceId = Guid.Parse("840F32FF-8B74-467C-8078-F5D9297FED56"); + public static String MerchantNumber = "12345678"; + public static String AddressLine1 = "AddressLine1"; + public static String AddressLine2 = "AddressLine2"; + public static String AddressLine3 = "AddressLine3"; + public static String AddressLine4 = "AddressLine4"; + public static String Country = "Country"; + public static String PostCode = "PostCode"; + public static String Region = "Region"; + public static String Town = "Town"; + public static TransactionProcessor.DataTransferObjects.Responses.Merchant.AddressResponse Address => + new TransactionProcessor.DataTransferObjects.Responses.Merchant.AddressResponse + { + AddressLine1 = TestData.AddressLine1, + AddressLine2 = TestData.AddressLine2, + AddressLine3 = TestData.AddressLine3, + AddressLine4 = TestData.AddressLine4, + Country = TestData.Country, + PostalCode = TestData.PostCode, + Region = TestData.Region, + Town = TestData.Town + }; + public static String ContactName = "Test Contact"; + public static String ContactPhone = "123456789"; + public static String ContactEmail = "testcontact1@testmerchant1.co.uk"; + public static TransactionProcessor.DataTransferObjects.Responses.Contract.ContactResponse Contact => + new () + { + ContactName = TestData.ContactName, + ContactEmailAddress = TestData.ContactEmail, + ContactPhoneNumber = TestData.ContactPhone + }; + public static String TerminalNumber = "00000001"; + public static TransactionProcessor.DataTransferObjects.Responses.Merchant.MerchantResponse MerchantResponse(TransactionProcessor.DataTransferObjects.Responses.Merchant.SettlementSchedule settlementSchedule) => + new() + { + EstateId = TestData.EstateId, + MerchantId = TestData.MerchantId, + MerchantName = TestData.MerchantName, + Devices = new Dictionary + { + {TestData.DeviceId, TestData.DeviceIdentifier} + }, + Operators = new() + { + new() + { + OperatorId = TestData.OperatorId, + MerchantNumber = TestData.MerchantNumber, + TerminalNumber = TestData.TerminalNumber + } + }, + Contracts = new(){ + new (){ + ContractId = TestData.ContractId, + ContractProducts = new List(){ + TestData.ProductId + } + } + }, + SettlementSchedule = settlementSchedule, + Addresses = new (){ + Address + }, + Contacts = new (){ + Contact + }, + }; + public static List MerchantContractResponses(TransactionProcessor.DataTransferObjects.Responses.Contract.ProductType productType) => + new() { + new() { + ContractId = TestData.ContractId, + Products = new() { + new () { + ProductId = TestData.ProductId, + ProductType = productType + } + } + } + }; } } \ No newline at end of file