diff --git a/.github/workflows/pullrequest.yml b/.github/workflows/pullrequest.yml index 93c1200f..2dab3b39 100644 --- a/.github/workflows/pullrequest.yml +++ b/.github/workflows/pullrequest.yml @@ -35,11 +35,11 @@ jobs: - name: Run Unit Tests run: | echo "ASPNETCORE_ENVIRONMENT are > ${ASPNETCORE_ENVIRONMENT}" - dotnet test "TransactionProcessor.BusinessLogic.Tests\TransactionProcessor.BusinessLogic.Tests.csproj" - dotnet test "TransactionProcessor.ProjectionEngine.Tests\TransactionProcessor.ProjectionEngine.Tests.csproj" - dotnet test "TransactionProcessor.Aggregates.Tests\TransactionProcessor.Aggregates.Tests.csproj" - dotnet test "TransactionProcessor.Tests\TransactionProcessor.Tests.csproj" - dotnet test "TransactionProcessor.DatabaseTests\TransactionProcessor.DatabaseTests.csproj" + dotnet test "TransactionProcessor.BusinessLogic.Tests\TransactionProcessor.BusinessLogic.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=buslogic-test-results.trx" + dotnet test "TransactionProcessor.ProjectionEngine.Tests\TransactionProcessor.ProjectionEngine.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=projection-test-results.trx" + dotnet test "TransactionProcessor.Aggregates.Tests\TransactionProcessor.Aggregates.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=aggregates-test-results.trx" + dotnet test "TransactionProcessor.Tests\TransactionProcessor.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=tests-test-results.trx" + dotnet test "TransactionProcessor.DatabaseTests\TransactionProcessor.DatabaseTests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=database-test-results.trx" - name: Build Docker Image run: docker build . --file TransactionProcessor/Dockerfile --tag transactionprocessor:latest @@ -59,10 +59,27 @@ jobs: FLUENTDOCKER_DOCKER_USE_SUDO: "false" FLUENTDOCKER_DOCKER_PATH: "/usr/bin/docker" run: | - dotnet test "TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj" --filter Category=PRTest + dotnet test "TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj" --filter Category=PRTest --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=integration-test-results.trx" - uses: actions/upload-artifact@v4.4.0 if: ${{ failure() }} with: name: tracelogs path: /home/txnproc/trace/ + + - name: Publish test results + uses: dorny/test-reporter@v1 + if: always() + with: + name: Unit Test Results + path: '**/TestResults/*.trx' + reporter: dotnet-trx + fail-on-error: true + + - name: Upload test results + uses: actions/upload-artifact@v4 + if: always() + with: + name: test-results + path: '**/TestResults/*.trx' + retention-days: 30 diff --git a/TransactionProcessor.Aggregates/OperatorAggregate.cs b/TransactionProcessor.Aggregates/OperatorAggregate.cs index 0691e4bd..37213d18 100644 --- a/TransactionProcessor.Aggregates/OperatorAggregate.cs +++ b/TransactionProcessor.Aggregates/OperatorAggregate.cs @@ -65,6 +65,9 @@ public static Result UpdateOperator(this OperatorAggregate aggregate, Boolean requireCustomMerchantNumber, Boolean requireCustomTerminalNumber) { + if (aggregate.IsCreated == false) + return Result.Invalid("Operator has not been created"); + if (String.Compare(name, aggregate.Name, StringComparison.InvariantCultureIgnoreCase) != 0 && String.IsNullOrEmpty(name) == false) { diff --git a/TransactionProcessor.BusinessLogic.Tests/Services/OperatorDomainServiceTests.cs b/TransactionProcessor.BusinessLogic.Tests/Services/OperatorDomainServiceTests.cs index f46ac285..400c6c14 100644 --- a/TransactionProcessor.BusinessLogic.Tests/Services/OperatorDomainServiceTests.cs +++ b/TransactionProcessor.BusinessLogic.Tests/Services/OperatorDomainServiceTests.cs @@ -7,7 +7,9 @@ using Shouldly; using SimpleResults; using TransactionProcessor.Aggregates; +using TransactionProcessor.BusinessLogic.Requests; using TransactionProcessor.BusinessLogic.Services; +using TransactionProcessor.DataTransferObjects.Requests.Operator; using TransactionProcessor.Testing; using Xunit; @@ -37,6 +39,28 @@ public async Task OperatorDomainService_CreateOperator_OperatorIsCreated(){ } + [Fact] + public async Task OperatorDomainService_CreateOperator_OperatorIdIsEmpty_OperatorIsCreated() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate()); + this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate())); + this.AggregateService + .Setup(o => o.Save(It.IsAny(), It.IsAny())).ReturnsAsync(Result.Success()); + + OperatorCommands.CreateOperatorCommand emptyIdCommand = new(TestData.EstateId, + new CreateOperatorRequest { + OperatorId = Guid.Empty, + Name = TestData.OperatorName, + RequireCustomMerchantNumber = TestData.RequireCustomMerchantNumber, + RequireCustomTerminalNumber = TestData.RequireCustomTerminalNumber + }); + + Result result = await this.OperatorDomainService.CreateOperator(emptyIdCommand, CancellationToken.None); + result.IsSuccess.ShouldBeTrue(); + } + [Fact] public async Task OperatorDomainService_CreateOperator_EstateNotCreated_ResultFailed() { @@ -60,6 +84,26 @@ public async Task OperatorDomainService_CreateOperator_OperatorAlreadyCreated_Re result.IsFailed.ShouldBeTrue(); } + [Fact] + public async Task OperatorDomainService_CreateOperator_OperatorNameEmpty_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate()); + this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate())); + + OperatorCommands.CreateOperatorCommand emptyNameCommand = new(TestData.EstateId, + new CreateOperatorRequest { + OperatorId = TestData.OperatorId, + Name = string.Empty, + RequireCustomMerchantNumber = TestData.RequireCustomMerchantNumber, + RequireCustomTerminalNumber = TestData.RequireCustomTerminalNumber + }); + + Result result = await this.OperatorDomainService.CreateOperator(emptyNameCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + [Fact] public async Task OperatorDomainService_UpdateOperator_OperatorIsUpdated() { @@ -75,9 +119,115 @@ public async Task OperatorDomainService_UpdateOperator_OperatorIsUpdated() [Fact] public async Task OperatorDomainService_UpdateOperator_OperatorNotCreated_ResultFailed() { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate()); this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())).ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate())); Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None); result.IsFailed.ShouldBeTrue(); } + + [Fact] + public async Task OperatorDomainService_CreateOperator_GetEstateFailed_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_CreateOperator_GetOperatorFailed_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate()); + this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_CreateOperator_SaveFailed_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate()); + this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate())); + this.AggregateService.Setup(o => o.Save(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_CreateOperator_ExceptionThrown_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception()); + + Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_UpdateOperator_GetEstateFailed_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_UpdateOperator_EstateNotCreated_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.EmptyEstateAggregate); + this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.CreatedOperatorAggregate())); + + Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_UpdateOperator_GetOperatorFailed_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate()); + this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_UpdateOperator_SaveFailed_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate()); + this.AggregateService.Setup(o => o.GetLatest(It.IsAny(), It.IsAny())) + .ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.CreatedOperatorAggregate())); + this.AggregateService.Setup(o => o.Save(It.IsAny(), It.IsAny())) + .ReturnsAsync(Result.Failure()); + + Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } + + [Fact] + public async Task OperatorDomainService_UpdateOperator_ExceptionThrown_ResultFailed() + { + this.AggregateService.Setup(e => e.Get(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Exception()); + + Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None); + result.IsFailed.ShouldBeTrue(); + } } \ No newline at end of file diff --git a/TransactionProcessor.BusinessLogic/Services/OperatorDomainService.cs b/TransactionProcessor.BusinessLogic/Services/OperatorDomainService.cs index ae4080e6..5bcd2856 100644 --- a/TransactionProcessor.BusinessLogic/Services/OperatorDomainService.cs +++ b/TransactionProcessor.BusinessLogic/Services/OperatorDomainService.cs @@ -42,7 +42,7 @@ public async Task CreateOperator(OperatorCommands.CreateOperatorCommand return ResultHelpers.CreateFailure(estateResult); Result operatorResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest(operatorId, ct), operatorId, cancellationToken, false); - if (estateResult.IsFailed) + if (operatorResult.IsFailed) return ResultHelpers.CreateFailure(operatorResult); EstateAggregate estateAggregate = estateResult.Data; @@ -80,7 +80,7 @@ public async Task UpdateOperator(OperatorCommands.UpdateOperatorCommand return ResultHelpers.CreateFailure(estateResult); Result operatorResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest(command.OperatorId, ct), command.OperatorId, cancellationToken); - if (estateResult.IsFailed) + if (operatorResult.IsFailed) return ResultHelpers.CreateFailure(operatorResult); EstateAggregate estateAggregate = estateResult.Data;