Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: update unit test for domain layer #5

Merged
merged 1 commit into from
Aug 6, 2024
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
9 changes: 9 additions & 0 deletions BuildingBlocks.sln
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Core", "Core", "{CFE5A713-D
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Infrastructure", "Infrastructure", "{9BFF2EA3-E081-4A2B-8297-A028DDD73E4A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{DC3F11D0-5517-44CC-B4D8-D2FB6282B874}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{06A00771-DEB6-4D06-A233-2B10B091295D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -66,6 +70,10 @@ Global
{C9891FE2-E5C6-4773-BCA0-919FDCC132D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C9891FE2-E5C6-4773-BCA0-919FDCC132D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C9891FE2-E5C6-4773-BCA0-919FDCC132D2}.Release|Any CPU.Build.0 = Release|Any CPU
{DC3F11D0-5517-44CC-B4D8-D2FB6282B874}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DC3F11D0-5517-44CC-B4D8-D2FB6282B874}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DC3F11D0-5517-44CC-B4D8-D2FB6282B874}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DC3F11D0-5517-44CC-B4D8-D2FB6282B874}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{0C2BE5AF-98DD-4E1D-A385-98E6B2D8A3A2} = {37ABC0F6-39B9-4057-955A-BA2CFDB64811}
Expand All @@ -77,5 +85,6 @@ Global
{4E1A0628-01F4-4876-B943-AC9FAFB19238} = {9BFF2EA3-E081-4A2B-8297-A028DDD73E4A}
{2667E7B6-8451-4842-9CC5-0663C8CAE5F4} = {9BFF2EA3-E081-4A2B-8297-A028DDD73E4A}
{C9891FE2-E5C6-4773-BCA0-919FDCC132D2} = {9BFF2EA3-E081-4A2B-8297-A028DDD73E4A}
{DC3F11D0-5517-44CC-B4D8-D2FB6282B874} = {06A00771-DEB6-4D06-A233-2B10B091295D}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace BuildingBlock.Core.Application.EventBus.Implementations;

public class EventBusSubscriptionsManager : IEventBusSubscriptionsManager
{
private readonly List<Type> _eventTypes = new();
private readonly List<Type> _eventTypes = [];
private readonly Dictionary<string, List<Type>> _handlers = new();

public bool IsEmpty => _handlers is { Count: 0 };
Expand Down Expand Up @@ -63,7 +63,7 @@ public string GetEventKey<T>()

private void DoAddSubscription(Type handlerType, string eventName)
{
if (!HasSubscriptionsForEvent(eventName)) _handlers.Add(eventName, new List<Type>());
if (!HasSubscriptionsForEvent(eventName)) _handlers.Add(eventName, []);

if (_handlers[eventName].Any(type => type == handlerType))
throw new ArgumentException(
Expand Down
5 changes: 3 additions & 2 deletions Core/BuildingBlock.Core.Domain/BaseEntity.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Collections;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Reflection;
Expand Down Expand Up @@ -91,7 +92,7 @@ private void DeleteProperty(PropertyInfo propertyInfo, DateTime? deletedAt, stri

foreach (var value in propertyValues)
{
object?[] parameters = { deletedAt, deletedBy };
object?[] parameters = [deletedAt, deletedBy];
deleteMethod.Invoke(value, parameters);
}
}
Expand All @@ -118,7 +119,7 @@ private static bool IsAGenericList(Type type)

public abstract class AggregateRoot : Entity, IAggregateRoot
{
public List<IDomainEvent> DomainEvents { get; } = new();
public List<IDomainEvent> DomainEvents { get; } = [];

public void AddDomainEvent(IDomainEvent domainEvent)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ protected EntityNotFoundException(string entity, string id) : base(
{
}

public EntityNotFoundException(string message) : base(message)
protected EntityNotFoundException(string message) : base(message)
{
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@ namespace BuildingBlock.Core.Domain.Rules.Abstractions;

public interface IBusinessRule
{
string Message { get; }
string? Message { get; }
bool IsBroken();
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public EmailAddressMustFollowPattern(string email)
_email = email;
}

public string? Message { get; private set; }

public bool IsBroken()
{
try
Expand All @@ -21,9 +23,13 @@ public bool IsBroken()
}
catch (FormatException)
{
Message = $"Email address: '{_email}' is not valid.";
return true;
}
catch (ArgumentException)
{
Message = $"Email address: '{_email}' can not be empty.";
return true;
}
}

public string Message => $"Email address: '{_email}' is not valid.";
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,20 @@ public class StringCanNotBeEmptyOrWhiteSpaceRule : IBusinessRule
private readonly string _name;
private readonly string? _value;

protected StringCanNotBeEmptyOrWhiteSpaceRule(string? value, string name)

public StringCanNotBeEmptyOrWhiteSpaceRule(string? value, string name)
{
_value = value;
_name = name;
}

public string? Message { get; private set; }

public bool IsBroken()
{
return string.IsNullOrEmpty(_value) || string.IsNullOrWhiteSpace(_value);
}
if (!string.IsNullOrEmpty(_value) && !string.IsNullOrWhiteSpace(_value)) return false;

public string Message => $"{_name} can not be empty or contain only white spaces.";
Message = $"{_name} with value: {_value} can not be empty or contain only white spaces.";
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,6 @@ public static T BindAndGetConfig<T>(this IConfiguration configuration, string se

if (config == null) throw new Exception($"{sectionName} configuration is not provided.");

CheckForNullProperties(config, sectionName);

return config;
}

private static void CheckForNullProperties(object obj, string sectionName)
{
var properties = obj.GetType().GetProperties();

foreach (var property in properties)
{
var value = property.GetValue(obj, null);

if (value == null)
throw new Exception($"Property '{property.Name}' in section '{sectionName}' is missing.");
}
}
}
22 changes: 9 additions & 13 deletions Core/BuildingBlock.Core.Domain/Shared/Utils/Optional.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,30 +31,26 @@ public Optional<T> ThrowIfNotExist(Exception exception)

public T Get()
{
CheckIfInstanceIsNotNull();
CheckIfExist();
return _instance!;
}

public Optional<T> ThrowIfNotEqual(T value, Exception exception)
public Optional<T> ThrowIfNotEqual(T? value, Exception exception)
{
CheckIfInstanceIsNotNull();
if (Equals(_instance, value)) return this;

if (!_instance!.Equals(value)) throw exception;

return this;
throw exception;
}

public Optional<T> ThrowIfEqual(T value, Exception exception)
public Optional<T> ThrowIfEqual(T? value, Exception exception)
{
CheckIfInstanceIsNotNull();
if (!Equals(_instance, value)) return this;

if (_instance!.Equals(value)) throw exception;

return this;
throw exception;
}

private void CheckIfInstanceIsNotNull()
private void CheckIfExist()
{
if (_instance == null) throw new InvalidOperationException("No value present");
ThrowIfNotExist(new InvalidOperationException("Instance is null."));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,13 @@ public bool Equals(ValueObject? other)

protected abstract IEnumerable<object?> GetValues();

public override bool Equals(object? obj)
{
return obj is ValueObject other && EqualsTo(other);
}

public override int GetHashCode()
{
return GetValues().Aggregate(default(int), HashCode.Combine);
}

private bool EqualsTo(ValueObject other)
{
return GetValues().SequenceEqual(other.GetValues());
}

public static void CheckRule(IBusinessRule rule)
{
if (rule.IsBroken()) throw new ValidationException(rule.Message);
if (rule.IsBroken()) throw new ValidationException(rule.Message!);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static class FilterExtension
public static void SetSoftDeleteFilter(this ModelBuilder modelBuilder, Type entityType)
{
SetSoftDeleteFilterMethod.MakeGenericMethod(entityType)
.Invoke(null, new object[] { modelBuilder });
.Invoke(null, [modelBuilder]);
}

public static void SetSoftDeleteFilter<TEntity>(this ModelBuilder modelBuilder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ private async Task ProcessEvent(string eventName, string message)

await Task.Yield();

await (Task)concreteType.GetMethod("HandleAsync")?.Invoke(handler, new[] { integrationEvent })!;
await (Task)concreteType.GetMethod("HandleAsync")?.Invoke(handler, [integrationEvent])!;
}
}
else
Expand Down
130 changes: 130 additions & 0 deletions Tests/Core/Domain/BaseEntityTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
using BuildingBlock.Core.Domain;
using FluentAssertions;

namespace Tests.Core.Domain;

public class EntityTest
{
public class TestEntity : Entity
{
public TestEntity()
{
UpdatedAt = DateTime.Now;
UpdatedBy = "Test";
}

public List<TestEntity> TestEntities { get; set; } = [];
public List<int> TestInts { get; set; } = [1, 2, 3];
public List<string> TestStrings { get; set; } = [];
public TestEntity ChildEntity { get; set; } = null!;
}

public class ResetUpdatedTimeStamp
{
public class ShouldResetUpdatedTimeStamp
{
[Fact]
public void WhenInvoke()
{
// Arrange
var entity = new TestEntity();

// Act
entity.ResetUpdatedTimeStamp();

// Assert
entity.UpdatedAt.Should().BeNull();
entity.UpdatedBy.Should().BeNull();
}
}
}
}

public class AggregateRootTest
{
public class AddDomainEvent
{
public class ShouldAddDomainEvent
{
[Fact]
public void WhenInvoke()
{
// Arrange
var aggregateRoot = new TestAggregateRoot();
var domainEvent = new TestDomainEvent();

// Act
aggregateRoot.AddDomainEvent(domainEvent);

// Assert
aggregateRoot.DomainEvents.Should().Contain(domainEvent);
aggregateRoot.DomainEvents.Should().HaveCount(1);
}
}
}

public class RemoveDomainEvent
{
public class ShouldRemoveDomainEvent
{
[Fact]
public void WhenThatDomainEventIsExist()
{
// Arrange
var aggregateRoot = new TestAggregateRoot();
var domainEvent = new TestDomainEvent();
aggregateRoot.AddDomainEvent(domainEvent);

// Act
aggregateRoot.RemoveDomainEvent(domainEvent);

// Assert
aggregateRoot.DomainEvents.Should().NotContain(domainEvent);
aggregateRoot.DomainEvents.Should().HaveCount(0);
}
}

public class ShouldDoNothing
{
[Fact]
public void WhenThatDomainEventIsNotExist()
{
// Arrange
var aggregateRoot = new TestAggregateRoot();
var domainEvent = new TestDomainEvent();

// Act
aggregateRoot.RemoveDomainEvent(domainEvent);

// Assert
aggregateRoot.DomainEvents.Should().NotContain(domainEvent);
aggregateRoot.DomainEvents.Should().HaveCount(0);
}
}
}

public class ClearDomainEvent
{
public class ShouldRemoveAllDomainEvents
{
[Fact]
public void WhenInvoke()
{
// Arrange
var aggregateRoot = new TestAggregateRoot();
var domainEvent = new TestDomainEvent();
aggregateRoot.AddDomainEvent(domainEvent);
aggregateRoot.AddDomainEvent(domainEvent);
aggregateRoot.AddDomainEvent(domainEvent);
aggregateRoot.AddDomainEvent(domainEvent);

// Act
aggregateRoot.ClearDomainEvents();

// Assert
aggregateRoot.DomainEvents.Should().NotContain(domainEvent);
aggregateRoot.DomainEvents.Should().HaveCount(0);
}
}
}
}
Loading