From b07f31f75feab46ffa739dc5c427d14428edea15 Mon Sep 17 00:00:00 2001 From: Kyle Ratti Date: Tue, 30 Apr 2024 14:17:54 -0400 Subject: [PATCH] test: achieve 100% coverage of Maybe --- Base.Tests/Structures/MaybeTests.cs | 339 +++++++++++++++++++++++++++- Base/Structures/Maybe.cs | 62 +++-- 2 files changed, 385 insertions(+), 16 deletions(-) diff --git a/Base.Tests/Structures/MaybeTests.cs b/Base.Tests/Structures/MaybeTests.cs index e6ce9c2..e3a6791 100644 --- a/Base.Tests/Structures/MaybeTests.cs +++ b/Base.Tests/Structures/MaybeTests.cs @@ -1,4 +1,5 @@ -using FruityFoundation.Base.Structures; +using System; +using FruityFoundation.Base.Structures; using NUnit.Framework; namespace Base.Tests.Structures; @@ -148,4 +149,340 @@ public class MaybeTests Assert.That(result.HasValue, Is.True); Assert.That(result.Value, Is.EqualTo(25)); } + + [Test] + public void Cast_ReturnsMaybe_WhenNewCastIsInvalid() + { + // Arrange + var maybe = Maybe.Create(25); + + // Act + var result = maybe.Cast(); + + // Assert + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.HasValue, Is.False); + } + + [Test] + public void Cast_ReturnsEmptyMaybe_WhenValueIsNull() + { + // Arrange + var maybe = Maybe.Create((string?)null); + + // Act + var result = maybe.Cast(); + + // Assert + Assert.That(result, Is.InstanceOf>()); + Assert.That(result.HasValue, Is.False); + } + + [Test] + public void Maybe_ValueType_OrValue_ReturnsProvidedValue_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.OrValue(25); + + // Assert + Assert.That(result, Is.EqualTo(25)); + } + + [Test] + public void Maybe_ValueType_OrValue_ReturnsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create(25); + + // Act + var result = maybe.OrValue(321); + + // Assert + Assert.That(result, Is.EqualTo(25)); + } + + [Test] + public void Maybe_ReferenceType_OrValue_ReturnsProvidedValue_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.OrValue("banana"); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_ReferenceType_OrValue_ReturnsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + var result = maybe.OrValue("pears"); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_ValueType_OrValueFactory_ReturnsOrValue_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.OrEval(() => 25); + + // Assert + Assert.That(result, Is.EqualTo(25)); + } + + [Test] + public void Maybe_ValueType_OrValueFactory_ReturnsOrValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create(25); + + // Act + var result = maybe.OrEval(() => 321); + + // Assert + Assert.That(result, Is.EqualTo(25)); + } + + [Test] + public void Maybe_ReferenceType_OrValueFactory_ReturnsOrValue_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.OrEval(() => "banana"); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_ReferenceType_OrValueFactory_ReturnsOrValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + var result = maybe.OrEval(() => "pears"); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_Try_ReturnsFalse_OutputsDefault_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + string? output; + var result = maybe.Try(out output); + + // Assert + Assert.That(result, Is.False); + Assert.That(output, Is.Default); + } + + [Test] + public void Maybe_Try_RetunsTrue_OutputsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + string? output; + var result = maybe.Try(out output); + + // Assert + Assert.That(result, Is.True); + Assert.That(output, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_OrThrow_ThrowsMessage_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = Assert.Throws(() => maybe.OrThrow("This cannot be empty!")); + + // Assert + Assert.That(result, Is.InstanceOf()); + Assert.That(result.Message, Is.EqualTo("This cannot be empty!")); + } + + [Test] + public void Maybe_OrThrow_ReturnsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + var result = maybe.OrThrow("This cannot be empty!"); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_OrThrowMessageFactory_ThrowsMessage_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = Assert.Throws(() => maybe.OrThrow(messageFactory: () => "This cannot be empty!")); + + // Assert + Assert.That(result, Is.InstanceOf()); + Assert.That(result.Message, Is.EqualTo("This cannot be empty!")); + } + + [Test] + public void Maybe_OrThrowMessageFactory_ReturnsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + var result = maybe.OrThrow(messageFactory: () => "This cannot be empty!"); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_OrThrowExceptionFactory_ThrowsMessage_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = Assert.Throws(() => maybe.OrThrow(exFactory: () => new InvalidOperationException("This cannot be empty!"))); + + // Assert + Assert.That(result, Is.InstanceOf()); + Assert.That(result.Message, Is.EqualTo("This cannot be empty!")); + } + + [Test] + public void Maybe_OrThrowExceptionFactory_ReturnsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + var result = maybe.OrThrow(exFactory: () => new InvalidOperationException("This cannot be empty!")); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_Map_ReturnsNewEmptyType_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.Map(x => x.ToString()); + + // Assert + Assert.That(result.HasValue, Is.False); + } + + [Test] + public void Maybe_Map_ReturnsNewMaybeWithValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create(25); + + // Act + var result = maybe.Map(x => x.ToString()); + + // Assert + Assert.That(result.HasValue, Is.True); + Assert.That(result.Value, Is.EqualTo("25")); + } + + [Test] + public void Maybe_Value_Throws_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = Assert.Throws(() => _ = maybe.Value); + + // Assert + Assert.That(result, Is.InstanceOf()); + Assert.That(result.Message, Is.EqualTo("Maybe value is empty")); + } + + [Test] + public void Maybe_Value_ReturnsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + var result = maybe.Value; + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } + + [Test] + public void Maybe_ToString_ReturnsPlaceholder_WhenEmpty() + { + // Arrange + var maybe = Maybe.Empty(); + + // Act + var result = maybe.ToString(); + + // Assert + Assert.That(result, Is.EqualTo("")); + } + + [Test] + public void Maybe_ToString_ReturnsNullPlaceholder_WhenValueIsNull() + { + // Arrange + var maybe = Maybe.Create((string?)null); + + // Act + var result = maybe.ToString(); + + // Assert + Assert.That(result, Is.EqualTo("")); + } + + [Test] + public void Maybe_ToString_ReturnsValue_WhenNotEmpty() + { + // Arrange + var maybe = Maybe.Create("banana"); + + // Act + var result = maybe.ToString(); + + // Assert + Assert.That(result, Is.EqualTo("banana")); + } } diff --git a/Base/Structures/Maybe.cs b/Base/Structures/Maybe.cs index 13c88c7..6233ea7 100644 --- a/Base/Structures/Maybe.cs +++ b/Base/Structures/Maybe.cs @@ -36,9 +36,21 @@ public readonly record struct Maybe } } - public T OrValue(T orVal) => HasValue ? Value : orVal; + public T OrValue(T orVal) + { + if (!HasValue) + return orVal; - public T OrEval(Func valueFactory) => HasValue ? Value : valueFactory(); + return Value; + } + + public T OrEval(Func valueFactory) + { + if (!HasValue) + return valueFactory(); + + return Value; + } public bool Try(out T val) { @@ -47,17 +59,38 @@ public readonly record struct Maybe return HasValue; } - public T OrThrow(string msg) => - HasValue ? Value : throw new Exception(msg); + public T OrThrow(string msg) + { + if (!HasValue) + throw new ApplicationException(msg); - public T OrThrow(Func messageFactory) => - HasValue ? Value : throw new Exception(messageFactory()); + return Value; + } - public T OrThrow(Func exFactory) => - HasValue ? Value : throw exFactory(); + public T OrThrow(Func messageFactory) + { + if (!HasValue) + throw new ApplicationException(messageFactory()); - public Maybe Map(Func transformer) => - HasValue ? Maybe.Create(transformer(Value)) : Maybe.Empty(); + return Value; + } + + public T OrThrow(Func exFactory) + { + if (!HasValue) + throw exFactory(); + + return Value; + } + + public Maybe Map(Func transformer) + { + if (!HasValue) + return Maybe.Empty(); + + var newValue = transformer(Value); + return new Maybe(newValue); + } public Maybe Bind(Func> binder) => HasValue ? binder(Value) : Maybe.Empty(); @@ -95,12 +128,11 @@ public readonly record struct Maybe public static implicit operator Maybe(T val) => Maybe.Create(val); - public static explicit operator T(Maybe val) => val.Value; - public override string ToString() { - return (Try(out var val) - ? val?.ToString() - : base.ToString())!; + if (!HasValue) + return ""; + + return _value?.ToString() ?? ""; } }