Genral clean up and moving of code.

This commit is contained in:
2026-07-30 17:01:33 +02:00
parent b37ca9222d
commit 2abe392890
19 changed files with 141 additions and 18 deletions
@@ -118,6 +118,12 @@ public class ApplyFeeHandlerTests
using var _ = new AssertionScope();
customerWrite.Entity.Balance.Should()
.Be(expectedBalance);
revenueWrite.Entity.Balance.Should()
.Be(feeAmount);
journalWrite.Should()
.NotBeNull();
@event.Should()
.NotBeNull();
}
}
}
@@ -1,8 +1,8 @@
using FinancialApi.Application.Commands;
using FinancialApi.Application.Events;
using FinancialApi.Application.Handlers;
using FinancialApi.Application.Models;
using FinancialApi.Domain.Entities;
using FinancialApi.Domain.Events;
using FluentAssertions;
using FluentAssertions.Execution;
using Microsoft.Extensions.Time.Testing;
@@ -1,9 +1,9 @@
using FinancialApi.Application.Commands;
using FinancialApi.Application.Events;
using FinancialApi.Application.Interfaces;
using FinancialApi.Application.Models;
using FinancialApi.Domain.Aggregates;
using FinancialApi.Domain.Entities;
using FinancialApi.Domain.Events;
using Wolverine.Persistence;
namespace FinancialApi.Application.Handlers;
@@ -1,4 +1,4 @@
using FinancialApi.Application.Events;
using FinancialApi.Domain.Events;
using Microsoft.Extensions.Logging;
namespace FinancialApi.Application.Handlers;
@@ -1,9 +1,9 @@
using FinancialApi.Application.Commands;
using FinancialApi.Application.Events;
using FinancialApi.Application.Interfaces;
using FinancialApi.Application.Models;
using FinancialApi.Domain.Aggregates;
using FinancialApi.Domain.Entities;
using FinancialApi.Domain.Events;
using Wolverine.Persistence;
namespace FinancialApi.Application.Handlers;
@@ -1,9 +1,9 @@
using FinancialApi.Application.Commands;
using FinancialApi.Application.Events;
using FinancialApi.Application.Interfaces;
using FinancialApi.Application.Models;
using FinancialApi.Domain.Aggregates;
using FinancialApi.Domain.Entities;
using FinancialApi.Domain.Events;
using Wolverine.Persistence;
namespace FinancialApi.Application.Handlers;
@@ -1,3 +1,3 @@
namespace FinancialApi.Application.Events;
namespace FinancialApi.Domain.Events;
public record FeeAppliedEvent(int AccountId, decimal Amount);
@@ -1,3 +1,3 @@
namespace FinancialApi.Application.Events;
namespace FinancialApi.Domain.Events;
public record FundsTransferredEvent(int SourceAccountId, int DestinationAccountId, decimal Amount);
@@ -1,4 +1,4 @@
namespace FinancialApi.Application.Events;
namespace FinancialApi.Domain.Events;
public interface IEventTracker
{
@@ -1,3 +1,3 @@
namespace FinancialApi.Application.Events;
namespace FinancialApi.Domain.Events;
public record JournalReversedEvent(Guid OriginalJournalId, Guid ReversalJournalId);
@@ -0,0 +1,35 @@
using FinancialApi.Application.Commands;
using FinancialApi.Application.Interfaces;
using FinancialApi.Domain.Entities;
using FinancialApi.Domain.Events;
using FluentAssertions;
using Wolverine;
using Wolverine.Tracking;
namespace FinancialApi.Infrastructure.Tests;
internal class FakeAccountQuery : IAccountQuery
{
public Task<Account?> FindByIdAsync(int id) => Task.FromResult(new Account(id, 100.00m, AccountType.Debit))!;
}
public class ApplyFeeIntegrationTests(WolverineTestFixture fixture) : IClassFixture<WolverineTestFixture>
{
[Fact]
public async Task GivenValidCommand_WhenApplyingFee_ShouldPublishFeeAppliedEvent()
{
// Arrange
var command = new ApplyFeeCommand(1, 100);
// Act
var session = await fixture.Host.InvokeMessageAndWaitAsync(command);
// Assert
session.Sent.AllMessages()
.ShouldHaveMessageOfType<FeeAppliedEvent>();
session.Sent.MessagesOf<FeeAppliedEvent>()
.Count()
.Should()
.Be(1);
}
}
@@ -0,0 +1,41 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.4"/>
<PackageReference Include="FluentAssertions" Version="8.10.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.10" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.14.1"/>
<PackageReference Include="NSubstitute" Version="6.0.0" />
<PackageReference Include="WolverineFx" Version="6.24.1" />
<PackageReference Include="WolverineFx.RuntimeCompilation" Version="6.24.1" />
<PackageReference Include="xunit" Version="2.9.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.4"/>
</ItemGroup>
<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Extensions.Hosting">
<HintPath>..\..\..\..\..\..\.nuget\packages\microsoft.extensions.hosting\10.0.0\lib\net10.0\Microsoft.Extensions.Hosting.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Hosting.Abstractions" />
<Reference Include="Microsoft.Extensions.TimeProvider.Testing">
<HintPath>..\..\..\..\..\..\.nuget\packages\microsoft.extensions.timeprovider.testing\10.6.0\lib\net10.0\Microsoft.Extensions.TimeProvider.Testing.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\FinancialApi.Application\FinancialApi.Application.csproj" />
<ProjectReference Include="..\FinancialApi.Infrastructure\FinancialApi.Infrastructure.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,34 @@
using FinancialApi.Application.Handlers;
using FinancialApi.Application.Interfaces;
using FinancialApi.Domain.Events;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Time.Testing;
using Wolverine;
namespace FinancialApi.Infrastructure.Tests;
public class WolverineTestFixture : IDisposable
{
public IHost Host { get; }
public WolverineTestFixture()
{
// We build and start the host ONCE here
Host = Microsoft.Extensions.Hosting.Host.CreateDefaultBuilder()
.ConfigureServices((context, services) =>
{
services.AddSingleton<IAccountQuery>(_ => new FakeAccountQuery());
services.AddSingleton<TimeProvider>(_ => new FakeTimeProvider());
services.AddSingleton<IEventTracker>(_ => new DemoEventStore());
}
)
.UseWolverine(opts => { opts.Discovery.IncludeAssembly(typeof(ApplyFeeHandler).Assembly); })
.Start();
}
public void Dispose()
{
Host.Dispose();
}
}
@@ -6,9 +6,9 @@ namespace FinancialApi.Infrastructure;
public class AccountQuery(AccountDbContext db) : IAccountQuery
{
public Task<Account?> FindByIdAsync(int id)
public async Task<Account?> FindByIdAsync(int id)
{
return db.Accounts.AsNoTracking()
return await db.Accounts.AsNoTracking()
.FirstOrDefaultAsync(x => x.Id == id);
}
}
@@ -1,6 +1,6 @@
using FinancialApi.Application.Events;
using FinancialApi.Domain.Events;
namespace FinancialApi;
namespace FinancialApi.Infrastructure;
public class DemoEventStore : IEventTracker
{
@@ -1,3 +1,4 @@
using FinancialApi.Domain.Exceptions;
using Microsoft.AspNetCore.Diagnostics;
using Microsoft.AspNetCore.Mvc;
@@ -11,7 +12,7 @@ public class DomainExceptionHandler : IExceptionHandler
CancellationToken cancellationToken
)
{
if (exception is not (InvalidOperationException or ArgumentException))
if (exception is not (InvalidOperationException or ArgumentException or GaapViolationException))
{
return false;
}
@@ -7,8 +7,8 @@ Accept: application/json
Content-Type: application/json
{
"accountId": 1,
"amount": 50.0
"accountId": 2,
"amount": 100
}
### Transfer Between Accounts
@@ -28,7 +28,7 @@ POST {{FinancialApi_HostAddress}}/journal/reverse
Content-Type: application/json
{
"originalJournalId": "B65EB28C-7EC1-4B70-9069-06A61A4FE857",
"originalJournalId": "E7FB25DB-406F-4063-A4B0-DE6BB8292437",
"reason": "Incorrect Account Fee"
}
@@ -1,8 +1,8 @@
using FinancialApi;
using FinancialApi.Application.Commands;
using FinancialApi.Application.Events;
using FinancialApi.Application.Handlers;
using FinancialApi.Application.Interfaces;
using FinancialApi.Domain.Events;
using FinancialApi.Infrastructure;
using FinancialApi.ServiceDefaults;
using JasperFx.Resources;
@@ -14,6 +14,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FinancialApi.Application.Un
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FinancialApi.Domain.Tests", "FinancialApi.Domain.Tests\FinancialApi.Domain.Tests.csproj", "{C15E3FE0-6E3D-4FFC-892E-D469536ADC13}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "FinancialApi.Infrastructure.Tests", "FinancialApi.Infrastructure.Tests\FinancialApi.Infrastructure.Tests.csproj", "{8C1BA932-16F2-42B3-A07C-C589C31044B3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -48,5 +50,9 @@ Global
{C15E3FE0-6E3D-4FFC-892E-D469536ADC13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C15E3FE0-6E3D-4FFC-892E-D469536ADC13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C15E3FE0-6E3D-4FFC-892E-D469536ADC13}.Release|Any CPU.Build.0 = Release|Any CPU
{8C1BA932-16F2-42B3-A07C-C589C31044B3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8C1BA932-16F2-42B3-A07C-C589C31044B3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8C1BA932-16F2-42B3-A07C-C589C31044B3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8C1BA932-16F2-42B3-A07C-C589C31044B3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal