Skip to content

Commit 6c5c827

Browse files
committed
feat: add a Whaally.Domain.Testing package containing rudimentary test harnesses for testing domain behaviour
1 parent 0cc3de0 commit 6c5c827

File tree

8 files changed

+175
-1
lines changed

8 files changed

+175
-1
lines changed

Whaally.Domain.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ConsoleSample", "samples\Co
3232
EndProject
3333
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Whaally.Domain.Abstractions", "src\Whaally.Domain.Abstractions\Whaally.Domain.Abstractions.csproj", "{B941C601-66E6-4764-AC79-139A3484FF26}"
3434
EndProject
35+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Whaally.Domain.Testing", "src\Whaally.Domain.Testing\Whaally.Domain.Testing.csproj", "{F31853A3-42FA-4A3E-91F2-091D1CE94E04}"
36+
EndProject
3537
Global
3638
GlobalSection(SolutionConfigurationPlatforms) = preSolution
3739
Debug|Any CPU = Debug|Any CPU
@@ -78,6 +80,10 @@ Global
7880
{B941C601-66E6-4764-AC79-139A3484FF26}.Debug|Any CPU.Build.0 = Debug|Any CPU
7981
{B941C601-66E6-4764-AC79-139A3484FF26}.Release|Any CPU.ActiveCfg = Release|Any CPU
8082
{B941C601-66E6-4764-AC79-139A3484FF26}.Release|Any CPU.Build.0 = Release|Any CPU
83+
{F31853A3-42FA-4A3E-91F2-091D1CE94E04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
84+
{F31853A3-42FA-4A3E-91F2-091D1CE94E04}.Debug|Any CPU.Build.0 = Debug|Any CPU
85+
{F31853A3-42FA-4A3E-91F2-091D1CE94E04}.Release|Any CPU.ActiveCfg = Release|Any CPU
86+
{F31853A3-42FA-4A3E-91F2-091D1CE94E04}.Release|Any CPU.Build.0 = Release|Any CPU
8187
EndGlobalSection
8288
GlobalSection(SolutionProperties) = preSolution
8389
HideSolutionNode = FALSE
@@ -93,6 +99,7 @@ Global
9399
{9AF0C648-D5E4-4701-AEC4-5AC5B3166B9F} = {F34E58C9-5FE8-4ED5-B88D-02AEE1D30907}
94100
{BD192AB0-96AB-4483-97EE-8B71737A77F4} = {E88FF4B1-4D2E-415E-92BF-61E3829CDB9B}
95101
{B941C601-66E6-4764-AC79-139A3484FF26} = {675431A2-F61A-4941-A1A3-2EBFB596E44E}
102+
{F31853A3-42FA-4A3E-91F2-091D1CE94E04} = {675431A2-F61A-4941-A1A3-2EBFB596E44E}
96103
EndGlobalSection
97104
GlobalSection(ExtensibilityGlobals) = postSolution
98105
SolutionGuid = {68BCF0DD-5501-460A-B702-728C2A93C91C}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
using FluentResults;
2+
using Whaally.Domain.Abstractions;
3+
4+
namespace Whaally.Domain.Testing;
5+
6+
public abstract class CommandTest<TAggregate, TCommand> : DomainTest
7+
where TAggregate : class, IAggregate
8+
where TCommand : class, ICommand
9+
{
10+
public ICommandHandler Handler { get; }
11+
public TAggregate Aggregate { get; }
12+
public TCommand Command { get; }
13+
14+
public CommandHandlerContext<TAggregate> Context { get; }
15+
public Result Result { get; private init; }
16+
public IEnumerable<IEvent> Events { get; private init; }
17+
18+
public CommandTest(
19+
TAggregate aggregate,
20+
TCommand command)
21+
{
22+
Handler = Domain.GetCommandHandler(typeof(TCommand));
23+
Aggregate = aggregate;
24+
Command = command;
25+
26+
var id = Guid.NewGuid();
27+
28+
// ToDo: Fix this usage
29+
Context = new CommandHandlerContext<TAggregate>(Services, id.ToString())
30+
{
31+
ParentContext = default,
32+
Aggregate = Aggregate
33+
};
34+
35+
var output = Handler.Evaluate(Context, Command);
36+
37+
if (output.GetType().GenericTypeArguments.Any())
38+
Result = new Result().WithReasons(output.Reasons);
39+
else
40+
Result = (Result)output;
41+
42+
Events = Context.Events;
43+
}
44+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
using Microsoft.Extensions.DependencyInjection;
2+
using Whaally.Domain.Abstractions;
3+
4+
namespace Whaally.Domain.Testing;
5+
6+
public abstract class DomainTest
7+
{
8+
public IServiceProvider Services { get; init; }
9+
= new ServiceCollection()
10+
.AddDomain()
11+
.BuildServiceProvider();
12+
13+
public DomainContext Domain => Services.GetRequiredService<DomainContext>();
14+
public IAggregateHandlerFactory Factory => Services.GetRequiredService<IAggregateHandlerFactory>();
15+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using Whaally.Domain.Abstractions;
2+
3+
namespace Whaally.Domain.Testing;
4+
5+
public abstract class EventTest<TAggregate, TEvent> : DomainTest
6+
where TAggregate : class, IAggregate, new()
7+
where TEvent : class, IEvent
8+
{
9+
public IEventHandler<TAggregate, TEvent> Handler { get; }
10+
public TAggregate Aggregate { get; }
11+
public TEvent Event { get; }
12+
13+
public EventHandlerContext<TAggregate> Context { get; }
14+
public TAggregate UpdatedAggregate { get; }
15+
16+
public EventTest(
17+
IEventHandler<TAggregate, TEvent> handler,
18+
TAggregate aggregate,
19+
TEvent @event)
20+
{
21+
Handler = handler;
22+
Aggregate = aggregate;
23+
Event = @event;
24+
25+
var id = Guid.NewGuid();
26+
Context = new EventHandlerContext<TAggregate>(id.ToString())
27+
{
28+
ParentContext = default,
29+
Aggregate = Aggregate
30+
};
31+
32+
UpdatedAggregate = Handler.Apply(Context, Event);
33+
}
34+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
using FluentResults;
2+
using Whaally.Domain.Abstractions;
3+
4+
namespace Whaally.Domain.Testing;
5+
6+
public abstract class ServiceTest<TService> : DomainTest
7+
where TService : class, IService
8+
{
9+
public IServiceHandler<TService> Handler { get; }
10+
public TService Service { get; }
11+
12+
public ServiceHandlerContext Context { get; }
13+
public Result Result { get; private init; }
14+
public IEnumerable<ICommand> Commands { get; private init; }
15+
16+
public ServiceTest(
17+
IServiceHandler<TService> handler,
18+
TService service)
19+
{
20+
Handler = handler;
21+
Service = service;
22+
23+
var id = Guid.NewGuid();
24+
Context = new ServiceHandlerContext(Services)
25+
{
26+
ParentContext = default
27+
};
28+
29+
var output = Handler.Handle(Context, Service).Result;
30+
31+
if (output.GetType().GenericTypeArguments.Any())
32+
Result = new Result().WithReasons(output.Reasons);
33+
else
34+
Result = (Result)output;
35+
36+
Commands = Context.Commands.SelectMany(q => q.Messages);
37+
}
38+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>net6.0</TargetFramework>
5+
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
6+
</PropertyGroup>
7+
8+
<ItemGroup>
9+
<None Include="..\..\assets\whaally-logo.png" Pack="true" PackagePath="\" />
10+
</ItemGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
14+
</ItemGroup>
15+
16+
<ItemGroup>
17+
<ProjectReference Include="..\Whaally.Domain\Whaally.Domain.csproj" />
18+
</ItemGroup>
19+
20+
<PropertyGroup>
21+
<PackageId>Whaally.Domain.Testing</PackageId>
22+
<Description>Test helpers to validate the correct functioning of domain implementations.</Description>
23+
<PackageProjectUrl>https://github.com/whaally/domain</PackageProjectUrl>
24+
<RepositoryUrl>https://github.com/whaally/domain</RepositoryUrl>
25+
<PackageLicenseExpression>MIT</PackageLicenseExpression>
26+
<Copyright>Copyright (c) Whaally 2025</Copyright>
27+
<RepositoryType>git</RepositoryType>
28+
<Authors>Corstian Boerman</Authors>
29+
<Company>Whaally</Company>
30+
<PackageTags>ddd domain model abstraction distributed
31+
actor framework</PackageTags>
32+
<PackageIcon>whaally-logo.png</PackageIcon>
33+
<PackageReleaseNotes>$([System.IO.File]::ReadAllText("$(MSBuildProjectDirectory)\..\Whaally.Domain\release-notes.txt"))</PackageReleaseNotes>
34+
</PropertyGroup>
35+
</Project>

src/Whaally.Domain/Service/ServiceHandlerContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public IReadOnlyCollection<ICommandEnvelope> Commands
4343

4444
public IAggregateHandlerFactory Factory
4545
=> _services.GetRequiredService<IAggregateHandlerFactory>();
46-
46+
4747
/// <summary>
4848
/// Evaluates a service and when successfull, adds the resulting operations to the current commands basket.
4949
/// </summary>

src/Whaally.Domain/Whaally.Domain.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
</ItemGroup>
1111

1212
<ItemGroup>
13+
<PackageReference Include="Microsoft.Extensions.DependencyInjection" />
1314
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" />
1415
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="9.0.0" />
1516
</ItemGroup>

0 commit comments

Comments
 (0)