Skip to content

Commit f5e3bbc

Browse files
Merge pull request #1506 from TransactionProcessing/copilot/update-test-coverage-operator-service
Full test coverage for OperatorDomainService — fix dead code branches and missing edge cases
2 parents 690da8a + 3b97bf5 commit f5e3bbc

4 files changed

Lines changed: 178 additions & 8 deletions

File tree

.github/workflows/pullrequest.yml

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ jobs:
3535
- name: Run Unit Tests
3636
run: |
3737
echo "ASPNETCORE_ENVIRONMENT are > ${ASPNETCORE_ENVIRONMENT}"
38-
dotnet test "TransactionProcessor.BusinessLogic.Tests\TransactionProcessor.BusinessLogic.Tests.csproj"
39-
dotnet test "TransactionProcessor.ProjectionEngine.Tests\TransactionProcessor.ProjectionEngine.Tests.csproj"
40-
dotnet test "TransactionProcessor.Aggregates.Tests\TransactionProcessor.Aggregates.Tests.csproj"
41-
dotnet test "TransactionProcessor.Tests\TransactionProcessor.Tests.csproj"
42-
dotnet test "TransactionProcessor.DatabaseTests\TransactionProcessor.DatabaseTests.csproj"
38+
dotnet test "TransactionProcessor.BusinessLogic.Tests\TransactionProcessor.BusinessLogic.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=buslogic-test-results.trx"
39+
dotnet test "TransactionProcessor.ProjectionEngine.Tests\TransactionProcessor.ProjectionEngine.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=projection-test-results.trx"
40+
dotnet test "TransactionProcessor.Aggregates.Tests\TransactionProcessor.Aggregates.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=aggregates-test-results.trx"
41+
dotnet test "TransactionProcessor.Tests\TransactionProcessor.Tests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=tests-test-results.trx"
42+
dotnet test "TransactionProcessor.DatabaseTests\TransactionProcessor.DatabaseTests.csproj" --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=database-test-results.trx"
4343
4444
- name: Build Docker Image
4545
run: docker build . --file TransactionProcessor/Dockerfile --tag transactionprocessor:latest
@@ -59,10 +59,27 @@ jobs:
5959
FLUENTDOCKER_DOCKER_USE_SUDO: "false"
6060
FLUENTDOCKER_DOCKER_PATH: "/usr/bin/docker"
6161
run: |
62-
dotnet test "TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj" --filter Category=PRTest
62+
dotnet test "TransactionProcessor.IntegrationTests/TransactionProcessor.IntegrationTests.csproj" --filter Category=PRTest --configuration Release --no-build --verbosity normal --logger "trx;LogFileName=integration-test-results.trx"
6363
6464
- uses: actions/upload-artifact@v4.4.0
6565
if: ${{ failure() }}
6666
with:
6767
name: tracelogs
6868
path: /home/txnproc/trace/
69+
70+
- name: Publish test results
71+
uses: dorny/test-reporter@v1
72+
if: always()
73+
with:
74+
name: Unit Test Results
75+
path: '**/TestResults/*.trx'
76+
reporter: dotnet-trx
77+
fail-on-error: true
78+
79+
- name: Upload test results
80+
uses: actions/upload-artifact@v4
81+
if: always()
82+
with:
83+
name: test-results
84+
path: '**/TestResults/*.trx'
85+
retention-days: 30

TransactionProcessor.Aggregates/OperatorAggregate.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,9 @@ public static Result UpdateOperator(this OperatorAggregate aggregate,
6565
Boolean requireCustomMerchantNumber,
6666
Boolean requireCustomTerminalNumber)
6767
{
68+
if (aggregate.IsCreated == false)
69+
return Result.Invalid("Operator has not been created");
70+
6871
if (String.Compare(name, aggregate.Name, StringComparison.InvariantCultureIgnoreCase) != 0 &&
6972
String.IsNullOrEmpty(name) == false)
7073
{

TransactionProcessor.BusinessLogic.Tests/Services/OperatorDomainServiceTests.cs

Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
using Shouldly;
88
using SimpleResults;
99
using TransactionProcessor.Aggregates;
10+
using TransactionProcessor.BusinessLogic.Requests;
1011
using TransactionProcessor.BusinessLogic.Services;
12+
using TransactionProcessor.DataTransferObjects.Requests.Operator;
1113
using TransactionProcessor.Testing;
1214
using Xunit;
1315

@@ -37,6 +39,28 @@ public async Task OperatorDomainService_CreateOperator_OperatorIsCreated(){
3739

3840
}
3941

42+
[Fact]
43+
public async Task OperatorDomainService_CreateOperator_OperatorIdIsEmpty_OperatorIsCreated()
44+
{
45+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
46+
.ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate());
47+
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
48+
.ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate()));
49+
this.AggregateService
50+
.Setup(o => o.Save(It.IsAny<OperatorAggregate>(), It.IsAny<CancellationToken>())).ReturnsAsync(Result.Success());
51+
52+
OperatorCommands.CreateOperatorCommand emptyIdCommand = new(TestData.EstateId,
53+
new CreateOperatorRequest {
54+
OperatorId = Guid.Empty,
55+
Name = TestData.OperatorName,
56+
RequireCustomMerchantNumber = TestData.RequireCustomMerchantNumber,
57+
RequireCustomTerminalNumber = TestData.RequireCustomTerminalNumber
58+
});
59+
60+
Result result = await this.OperatorDomainService.CreateOperator(emptyIdCommand, CancellationToken.None);
61+
result.IsSuccess.ShouldBeTrue();
62+
}
63+
4064
[Fact]
4165
public async Task OperatorDomainService_CreateOperator_EstateNotCreated_ResultFailed()
4266
{
@@ -60,6 +84,26 @@ public async Task OperatorDomainService_CreateOperator_OperatorAlreadyCreated_Re
6084
result.IsFailed.ShouldBeTrue();
6185
}
6286

87+
[Fact]
88+
public async Task OperatorDomainService_CreateOperator_OperatorNameEmpty_ResultFailed()
89+
{
90+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
91+
.ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate());
92+
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
93+
.ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate()));
94+
95+
OperatorCommands.CreateOperatorCommand emptyNameCommand = new(TestData.EstateId,
96+
new CreateOperatorRequest {
97+
OperatorId = TestData.OperatorId,
98+
Name = string.Empty,
99+
RequireCustomMerchantNumber = TestData.RequireCustomMerchantNumber,
100+
RequireCustomTerminalNumber = TestData.RequireCustomTerminalNumber
101+
});
102+
103+
Result result = await this.OperatorDomainService.CreateOperator(emptyNameCommand, CancellationToken.None);
104+
result.IsFailed.ShouldBeTrue();
105+
}
106+
63107
[Fact]
64108
public async Task OperatorDomainService_UpdateOperator_OperatorIsUpdated()
65109
{
@@ -75,9 +119,115 @@ public async Task OperatorDomainService_UpdateOperator_OperatorIsUpdated()
75119
[Fact]
76120
public async Task OperatorDomainService_UpdateOperator_OperatorNotCreated_ResultFailed()
77121
{
122+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
123+
.ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate());
78124
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>())).ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate()));
79125

80126
Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None);
81127
result.IsFailed.ShouldBeTrue();
82128
}
129+
130+
[Fact]
131+
public async Task OperatorDomainService_CreateOperator_GetEstateFailed_ResultFailed()
132+
{
133+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
134+
.ReturnsAsync(Result.Failure());
135+
136+
Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None);
137+
result.IsFailed.ShouldBeTrue();
138+
}
139+
140+
[Fact]
141+
public async Task OperatorDomainService_CreateOperator_GetOperatorFailed_ResultFailed()
142+
{
143+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
144+
.ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate());
145+
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
146+
.ReturnsAsync(Result.Failure());
147+
148+
Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None);
149+
result.IsFailed.ShouldBeTrue();
150+
}
151+
152+
[Fact]
153+
public async Task OperatorDomainService_CreateOperator_SaveFailed_ResultFailed()
154+
{
155+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
156+
.ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate());
157+
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
158+
.ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.EmptyOperatorAggregate()));
159+
this.AggregateService.Setup(o => o.Save(It.IsAny<OperatorAggregate>(), It.IsAny<CancellationToken>()))
160+
.ReturnsAsync(Result.Failure());
161+
162+
Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None);
163+
result.IsFailed.ShouldBeTrue();
164+
}
165+
166+
[Fact]
167+
public async Task OperatorDomainService_CreateOperator_ExceptionThrown_ResultFailed()
168+
{
169+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
170+
.ThrowsAsync(new Exception());
171+
172+
Result result = await this.OperatorDomainService.CreateOperator(TestData.Commands.CreateOperatorCommand, CancellationToken.None);
173+
result.IsFailed.ShouldBeTrue();
174+
}
175+
176+
[Fact]
177+
public async Task OperatorDomainService_UpdateOperator_GetEstateFailed_ResultFailed()
178+
{
179+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
180+
.ReturnsAsync(Result.Failure());
181+
182+
Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None);
183+
result.IsFailed.ShouldBeTrue();
184+
}
185+
186+
[Fact]
187+
public async Task OperatorDomainService_UpdateOperator_EstateNotCreated_ResultFailed()
188+
{
189+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
190+
.ReturnsAsync(TestData.Aggregates.EmptyEstateAggregate);
191+
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
192+
.ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.CreatedOperatorAggregate()));
193+
194+
Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None);
195+
result.IsFailed.ShouldBeTrue();
196+
}
197+
198+
[Fact]
199+
public async Task OperatorDomainService_UpdateOperator_GetOperatorFailed_ResultFailed()
200+
{
201+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
202+
.ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate());
203+
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
204+
.ReturnsAsync(Result.Failure());
205+
206+
Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None);
207+
result.IsFailed.ShouldBeTrue();
208+
}
209+
210+
[Fact]
211+
public async Task OperatorDomainService_UpdateOperator_SaveFailed_ResultFailed()
212+
{
213+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
214+
.ReturnsAsync(TestData.Aggregates.CreatedEstateAggregate());
215+
this.AggregateService.Setup(o => o.GetLatest<OperatorAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
216+
.ReturnsAsync(SimpleResults.Result.Success(TestData.Aggregates.CreatedOperatorAggregate()));
217+
this.AggregateService.Setup(o => o.Save(It.IsAny<OperatorAggregate>(), It.IsAny<CancellationToken>()))
218+
.ReturnsAsync(Result.Failure());
219+
220+
Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None);
221+
result.IsFailed.ShouldBeTrue();
222+
}
223+
224+
[Fact]
225+
public async Task OperatorDomainService_UpdateOperator_ExceptionThrown_ResultFailed()
226+
{
227+
this.AggregateService.Setup(e => e.Get<EstateAggregate>(It.IsAny<Guid>(), It.IsAny<CancellationToken>()))
228+
.ThrowsAsync(new Exception());
229+
230+
Result result = await this.OperatorDomainService.UpdateOperator(TestData.Commands.UpdateOperatorCommand, CancellationToken.None);
231+
result.IsFailed.ShouldBeTrue();
232+
}
83233
}

TransactionProcessor.BusinessLogic/Services/OperatorDomainService.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public async Task<Result> CreateOperator(OperatorCommands.CreateOperatorCommand
4242
return ResultHelpers.CreateFailure(estateResult);
4343

4444
Result<OperatorAggregate> operatorResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest<OperatorAggregate>(operatorId, ct), operatorId, cancellationToken, false);
45-
if (estateResult.IsFailed)
45+
if (operatorResult.IsFailed)
4646
return ResultHelpers.CreateFailure(operatorResult);
4747

4848
EstateAggregate estateAggregate = estateResult.Data;
@@ -80,7 +80,7 @@ public async Task<Result> UpdateOperator(OperatorCommands.UpdateOperatorCommand
8080
return ResultHelpers.CreateFailure(estateResult);
8181

8282
Result<OperatorAggregate> operatorResult = await DomainServiceHelper.GetAggregateOrFailure(ct => this.AggregateService.GetLatest<OperatorAggregate>(command.OperatorId, ct), command.OperatorId, cancellationToken);
83-
if (estateResult.IsFailed)
83+
if (operatorResult.IsFailed)
8484
return ResultHelpers.CreateFailure(operatorResult);
8585

8686
EstateAggregate estateAggregate = estateResult.Data;

0 commit comments

Comments
 (0)