Skip to content

Commit

Permalink
[BDB-12] Create PositiveIntegerRange base value object (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
phamhongphuc1403 authored Aug 16, 2024
1 parent 0e9b920 commit 05a3d4a
Show file tree
Hide file tree
Showing 11 changed files with 385 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using BuildingBlock.Core.Domain.Rules.Abstractions;

namespace BuildingBlock.Core.Domain.Rules.Implementations;

public class NumberMustBeGreaterThan : IBusinessRule
{
private readonly object _compareValue;
private readonly string? _compareValueName;
private readonly object _value;
private readonly string? _valueName;

public NumberMustBeGreaterThan(double value, double compareValue)
{
_compareValue = compareValue;
_value = value;
}

public NumberMustBeGreaterThan(int value, int compareValue)
{
_compareValue = compareValue;
_value = value;
}

public NumberMustBeGreaterThan(int value, int compareValue, string? valueName = null,
string? compareValueName = null) : this(value, compareValue)
{
_valueName = valueName;
_compareValueName = compareValueName;
}

public NumberMustBeGreaterThan(double value, double compareValue, string? valueName = null,
string? compareValueName = null) : this(value, compareValue)
{
_valueName = valueName;
_compareValueName = compareValueName;
}

public string? Message { get; private set; }


public bool IsBroken()
{
if (Convert.ToDouble(_value) > Convert.ToDouble(_compareValue)) return false;

var valueName = _valueName is not null ? $"{_valueName}: " : string.Empty;
var compareValueName = _compareValueName is not null ? $"{_compareValueName}: " : string.Empty;

Message = $"{valueName}{_value} must be greater than {compareValueName}{_compareValue}.";

return true;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
namespace BuildingBlock.Core.Domain.Rules.Implementations;

public class NumberMustBeGreaterThanZero : NumberMustBeGreaterThan
{
public NumberMustBeGreaterThanZero(int value) : base(value, 0)
{
}

public NumberMustBeGreaterThanZero(double value) : base(value, 0)
{
}

public NumberMustBeGreaterThanZero(int value, string? valueName = null) : base(value, 0, valueName)
{
}

public NumberMustBeGreaterThanZero(double value, string? valueName = null) : base(value, 0, valueName)
{
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using BuildingBlock.Core.Domain.Rules.Implementations;

namespace BuildingBlock.Core.Domain.ValueObjects.Abstractions;

public abstract class PositiveIntegerRange : ValueObject
{
protected PositiveIntegerRange(int minValue, int maxValue)
{
CheckRule(new NumberMustBeGreaterThanZero(minValue, $"The minimum value of the {this.ToNormalizedName()}"));
CheckRule(new NumberMustBeGreaterThan(maxValue, minValue, $"The maximum value of the {this.ToNormalizedName()}",
"the minimum value"));

MaxValue = maxValue;
MinValue = minValue;
}

public int MinValue { get; }
public int MaxValue { get; }

protected override IEnumerable<object?> GetValues()
{
return new object?[] { MinValue, MaxValue };
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using BuildingBlock.Core.Domain.ValueObjects.Abstractions;

namespace BuildingBlock.Core.Domain.ValueObjects.Implementations;

public class AgeRange : PositiveIntegerRange
{
public AgeRange(int minValue, int maxValue) : base(minValue, maxValue)
{
}
}
28 changes: 28 additions & 0 deletions Core/BuildingBlock.Core.Domain/ValueObjects/ValueObjectUtility.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Text;
using BuildingBlock.Core.Domain.ValueObjects.Abstractions;

namespace BuildingBlock.Core.Domain.ValueObjects;

public static class ValueObjectUtility
{
public static string ToNormalizedName(this ValueObject valueObject)
{
var name = valueObject.GetType().Name;
var stringBuilder = new StringBuilder(name.Length * 2); // Optimizes for potential growth

stringBuilder.Append(char.ToLower(name[0])); // Start with the first character in lowercase

for (var i = 1; i < name.Length; i++)
if (char.IsUpper(name[i]))
{
stringBuilder.Append(' ');
stringBuilder.Append(char.ToLower(name[i]));
}
else
{
stringBuilder.Append(name[i]);
}

return stringBuilder.ToString();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using BuildingBlock.Core.Domain.Rules.Implementations;
using FluentAssertions;

namespace Tests.Core.Domain.Rules;

public class NumberMustBeGreaterThanTest
{
public class ShouldReturnFalse
{
public class WhenValueIsLargerThanCompareValue
{
[Fact]
public void CaseInteger()
{
// Arrange
var numberMustLargerThanZero = new NumberMustBeGreaterThan(1, 0);

// Act
var result = numberMustLargerThanZero.IsBroken();

// Assert
result.Should().BeFalse();
numberMustLargerThanZero.Message.Should().BeNull();
}

[Fact]
public void CaseDouble()
{
// Arrange
var numberMustLargerThanZero = new NumberMustBeGreaterThan(1.1, 0.1);

// Act
var result = numberMustLargerThanZero.IsBroken();

// Assert
result.Should().BeFalse();
numberMustLargerThanZero.Message.Should().BeNull();
}
}
}

public class ShouldReturnTrue
{
public class WhenValueIsNotLargerThanCompareValue
{
[Fact]
public void CaseInteger()
{
// Arrange
var numberMustLargerThanZero = new NumberMustBeGreaterThan(1, 1, "value", "compare value");

// Act
var result = numberMustLargerThanZero.IsBroken();

// Assert
result.Should().BeTrue();
numberMustLargerThanZero.Message.Should().Be("value: 1 must be greater than compare value: 1.");
}

[Fact]
public void CaseDouble()
{
// Arrange
var numberMustLargerThanZero = new NumberMustBeGreaterThan(0.111111111111, 1.111111111111);

// Act
var result = numberMustLargerThanZero.IsBroken();

// Assert
result.Should().BeTrue();
numberMustLargerThanZero.Message.Should().Be("0,111111111111 must be greater than 1,111111111111.");
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
using BuildingBlock.Core.Domain.Rules.Implementations;
using FluentAssertions;

namespace Tests.Core.Domain.Rules;

public class NumberMustBeGreaterThanZeroTest
{
public class ShouldReturnTrue
{
public class WhenValueIsSmallerThanZero
{
[Fact]
public void CaseInteger()
{
// Arrange
var rule = new NumberMustBeGreaterThanZero(-1);

// Act
var result = rule.IsBroken();

// Assert
result.Should().BeTrue();
rule.Message.Should().Be("-1 must be greater than 0.");
}

[Fact]
public void CaseDouble()
{
// Arrange
var rule = new NumberMustBeGreaterThanZero(-1.1, "value");

// Act
var result = rule.IsBroken();

// Assert
result.Should().BeTrue();
rule.Message.Should().Be("value: -1,1 must be greater than 0.");
}
}
}

public class ShouldReturnFalse
{
public class WhenValueIsLargerThanZero
{
[Fact]
public void CaseInteger()
{
// Arrange
var rule = new NumberMustBeGreaterThanZero(1, "value");

// Act
var result = rule.IsBroken();

// Assert
result.Should().BeFalse();
rule.Message.Should().BeNull();
}

[Fact]
public void CaseDouble()
{
// Arrange
var rule = new NumberMustBeGreaterThanZero(1.1);

// Act
var result = rule.IsBroken();

// Assert
result.Should().BeFalse();
rule.Message.Should().BeNull();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using BuildingBlock.Core.Domain.Exceptions;
using BuildingBlock.Core.Domain.ValueObjects.Implementations;
using FluentAssertions;

namespace Tests.Core.Domain.ValueObjects.Implementations;

public class AgeRangeTest
{
public class ShouldThrowValidationException
{
[Fact]
public void WhenMinimumValueIsSmallerThanZero()
{
// Arrange
const int minValue = -1;
const int maxValue = 1;

// Act
var action = () => { _ = new AgeRange(minValue, maxValue); };

// Assert
action.Should().Throw<ValidationException>()
.WithMessage("The minimum value of the age range: -1 must be greater than 0.");
}

[Fact]
public void WhenMinimumValueIsGreaterThanMaximumValue()
{
// Arrange
const int minValue = 2;
const int maxValue = 1;

// Act
var action = () => { _ = new AgeRange(minValue, maxValue); };

// Assert
action.Should().Throw<ValidationException>()
.WithMessage("The maximum value of the age range: 1 must be greater than the minimum value: 2.");
}
}

public class ShouldCreateNewAgeRangeInstance
{
[Fact]
public void WhenMaximumValueIsGreaterThanMinimumValue()
{
// Arrange
const int minValue = 1;
const int maxValue = 2;

// Act
var ageRange = new AgeRange(minValue, maxValue);

// Assert
ageRange.MinValue.Should().Be(minValue);
ageRange.MaxValue.Should().Be(maxValue);
}
}
}
Loading

0 comments on commit 05a3d4a

Please sign in to comment.