Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="AutoFixture.Xunit2" Version="4.18.1" />
<PackageVersion Include="Azure.Core" Version="1.50.0" />
<PackageVersion Include="Azure.Core" Version="1.51.1" />
<PackageVersion Include="Azure.Identity" Version="[1.15.0, 2.0]" />
<PackageVersion Include="coverlet.collector" Version="6.0.4">
<PackageVersion Include="coverlet.collector" Version="8.0.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="FluentAssertions" Version="7.0.0" />
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.56.0" />
<PackageVersion Include="FluentAssertions" Version="7.2.2" />
<PackageVersion Include="Microsoft.Azure.Cosmos" Version="3.57.1" />
<PackageVersion Include="Nerdbank.GitVersioning" Version="3.9.50">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
Expand All @@ -21,32 +21,32 @@
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.SourceGenerators.Testing.XUnit" Version="1.1.2" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.0.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="8.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="8.0.8">
<PackageVersion Include="Microsoft.EntityFrameworkCore" Version="10.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.Design" Version="10.0.5">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageVersion>
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.8" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="8.0.8" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.1" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.1" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.1" />
<PackageVersion Include="MongoDB.Driver" Version="3.3.0" />
<PackageVersion Include="Moq" Version="4.18.4" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.InMemory" Version="10.0.5" />
<PackageVersion Include="Microsoft.EntityFrameworkCore.SqlServer" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.Caching.Memory" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Abstractions" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.Logging.Console" Version="10.0.5" />
<PackageVersion Include="Microsoft.Extensions.Options" Version="10.0.5" />
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
<PackageVersion Include="MongoDB.Driver" Version="3.7.0" />
<PackageVersion Include="Moq" Version="4.20.72" />
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
<PackageVersion Include="Papst.EventStore" Version="[5.4.0,5.5)" />
<PackageVersion Include="System.Formats.Asn1" Version="10.0.1" />
<PackageVersion Include="System.Linq.Async" Version="7.0.0" />
<PackageVersion Include="Testcontainers" Version="4.10.0" />
<PackageVersion Include="Testcontainers.CosmosDb" Version="4.10.0" />
<PackageVersion Include="Testcontainers.MongoDb" Version="4.10.0" />
<PackageVersion Include="Testcontainers" Version="4.11.0" />
<PackageVersion Include="Testcontainers.CosmosDb" Version="4.11.0" />
<PackageVersion Include="Testcontainers.MongoDb" Version="4.11.0" />
<PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.5">
<PrivateAssets>all</PrivateAssets>
Expand Down
29 changes: 29 additions & 0 deletions src/Papst.EventStore/Aggregation/EventAggregatorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,20 @@ protected void Update<TProperty>(TProperty? value, Action<TProperty> setter)
setter.Invoke(value);
}
}

/// <summary>
/// Executes the <paramref name="setter"/> action when <paramref name="value"/>.HasValue is true
/// </summary>
/// <typeparam name="TProperty"></typeparam>
/// <param name="value"></param>
/// <param name="setter"></param>
protected void Update<TProperty>(TProperty? value, Action<TProperty> setter) where TProperty : struct
{
if (value.HasValue)
{
setter.Invoke(value.Value);
}
}

/// <summary>
/// Executes the <paramref name="setter"/> action when <paramref name="value"/> is not null
Expand All @@ -41,6 +55,21 @@ protected void SetIfNotNull<TProperty>(Action<TProperty> setter, TProperty? valu
setter.Invoke(value);
}
}

/// <summary>
/// This overload is for nullable value types.
/// Executes the <paramref name="setter"/> action when <paramref name="value"/>.HasValue is true.
/// </summary>
/// <param name="setter"></param>
/// <param name="value"></param>
/// <typeparam name="TProperty"></typeparam>
protected void SetIfNotNull<TProperty>(Action<TProperty> setter, TProperty? value) where TProperty : struct
{
if (value.HasValue)
{
setter(value.Value);
}
}

/// <summary>
/// Returns the given Entity wrapped in a Task
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public class CosmosDbIntegrationTestFixture : IAsyncLifetime

private readonly CosmosDbContainer _cosmosDbContainer =
//new CosmosDbBuilder("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview")
new CosmosDbBuilder("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest")
new CosmosDbBuilder("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview")
.WithPortBinding(InternalPort, true)
//.WithEnvironment("AZURE_COSMOS_EMULATOR_PARTITION_COUNT", "10")
.WithEnvironment("AZURE_COSMOS_EMULATOR_ENABLE_DATA_PERSISTANCE", "false")
Expand Down
166 changes: 166 additions & 0 deletions tests/Papst.EventStore.Tests/EventAggregatorBaseTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
#nullable enable
using System;
using System.Threading.Tasks;
using FluentAssertions;
using Papst.EventStore.Aggregation;
using Xunit;

namespace Papst.EventStore.Tests;

public class EventAggregatorBaseTests
{
private readonly TestAggregator _sut = new();

[Fact]
public void SetIfNotNull_ShouldInvokeSetter_WhenNullableStructHasValue()
{
int result = 0;
int? value = 42;

_sut.CallSetIfNotNull<int>(v => result = v, value);

result.Should().Be(42);
}

[Fact]
public void SetIfNotNull_ShouldNotInvokeSetter_WhenNullableStructIsNull()
{
int result = 0;
int? value = null;

_sut.CallSetIfNotNull<int>(v => result = v, value);

result.Should().Be(0);
}

[Fact]
public void SetIfNotNull_ShouldInvokeSetter_WhenNullableDateTimeHasValue()
{
DateTime result = default;
DateTime? value = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc);

_sut.CallSetIfNotNull<DateTime>(v => result = v, value);

result.Should().Be(new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc));
}

[Fact]
public void SetIfNotNull_ShouldNotInvokeSetter_WhenNullableDateTimeIsNull()
{
DateTime result = default;
DateTime? value = null;

_sut.CallSetIfNotNull<DateTime>(v => result = v, value);

result.Should().Be(default(DateTime));
}

[Fact]
public void SetIfNotNull_ShouldInvokeSetter_WhenNullableGuidHasValue()
{
Guid result = Guid.Empty;
Guid expected = Guid.NewGuid();
Guid? value = expected;

_sut.CallSetIfNotNull<Guid>(v => result = v, value);

result.Should().Be(expected);
}

[Fact]
public void SetIfNotNull_ShouldNotInvokeSetter_WhenNullableGuidIsNull()
{
Guid result = Guid.Empty;
Guid? value = null;

_sut.CallSetIfNotNull<Guid>(v => result = v, value);

result.Should().Be(Guid.Empty);
}

[Fact]
public void Update_ShouldInvokeSetter_WhenNullableStructHasValue()
{
int result = 0;
int? value = 42;

_sut.CallUpdate<int>(value, v => result = v);

result.Should().Be(42);
}

[Fact]
public void Update_ShouldNotInvokeSetter_WhenNullableStructIsNull()
{
int result = 0;
int? value = null;

_sut.CallUpdate<int>(value, v => result = v);

result.Should().Be(0);
}

[Fact]
public void Update_ShouldInvokeSetter_WhenNullableDateTimeHasValue()
{
DateTime result = default;
DateTime? value = new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc);

_sut.CallUpdate<DateTime>(value, v => result = v);

result.Should().Be(new DateTime(2025, 1, 1, 0, 0, 0, DateTimeKind.Utc));
}

[Fact]
public void Update_ShouldNotInvokeSetter_WhenNullableDateTimeIsNull()
{
DateTime result = default;
DateTime? value = null;

_sut.CallUpdate<DateTime>(value, v => result = v);

result.Should().Be(default(DateTime));
}

[Fact]
public void Update_ShouldInvokeSetter_WhenNullableGuidHasValue()
{
Guid result = Guid.Empty;
Guid expected = Guid.NewGuid();
Guid? value = expected;

_sut.CallUpdate<Guid>(value, v => result = v);

result.Should().Be(expected);
}

[Fact]
public void Update_ShouldNotInvokeSetter_WhenNullableGuidIsNull()
{
Guid result = Guid.Empty;
Guid? value = null;

_sut.CallUpdate<Guid>(value, v => result = v);

result.Should().Be(Guid.Empty);
}

private class TestEntity
{
public int IntValue { get; set; }
}

private record TestEvent;

private class TestAggregator : EventAggregatorBase<TestEntity, TestEvent>
{
public override ValueTask<TestEntity?> ApplyAsync(TestEvent evt, TestEntity entity, IAggregatorStreamContext ctx)
=> AsTask(entity);

public void CallSetIfNotNull<T>(Action<T> setter, T? value) where T : struct
=> SetIfNotNull(setter, value);

public void CallUpdate<T>(T? value, Action<T> setter) where T : struct
=> Update(value, setter);
}
}
Loading