diff --git a/src/MrKWatkins.Assertions.Tests/AsyncActionAssertionsTests.cs b/src/MrKWatkins.Assertions.Tests/AsyncActionAssertionsTests.cs new file mode 100644 index 0000000..6ddd643 --- /dev/null +++ b/src/MrKWatkins.Assertions.Tests/AsyncActionAssertionsTests.cs @@ -0,0 +1,149 @@ +namespace MrKWatkins.Assertions.Tests; + +public sealed class AsyncActionAssertionsTests +{ + [Test] + public async Task ThrowAsync() + { + Func doesNotThrow = () => Task.CompletedTask; + Func doesNotThrowAsync = async () => await Task.Yield(); + + var exception = new InvalidOperationException("Test"); + Func throws = () => throw exception; + Func throwsAsync = async () => { await Task.Yield(); throw exception; }; + + Func throwsWrongException = () => throw new NotSupportedException("Wrong"); + Func throwsWrongExceptionAsync = async () => { await Task.Yield(); throw new NotSupportedException("Wrong"); }; + + await Assert.That(() => throws.Should().ThrowAsync()).ThrowsNothing(); + await Assert.That(() => throwsAsync.Should().ThrowAsync()).ThrowsNothing(); + + await Assert.That(() => doesNotThrow.Should().ThrowAsync()) + .Throws().WithMessage("Function should throw an InvalidOperationException."); + await Assert.That(() => doesNotThrowAsync.Should().ThrowAsync()) + .Throws().WithMessage("Function should throw an InvalidOperationException."); + + await Assert.That(() => throwsWrongException.Should().ThrowAsync()) + .Throws().WithMessage("Function should throw an InvalidOperationException but threw a NotSupportedException with message \"Wrong\"."); + await Assert.That(() => throwsWrongExceptionAsync.Should().ThrowAsync()) + .Throws().WithMessage("Function should throw an InvalidOperationException but threw a NotSupportedException with message \"Wrong\"."); + } + + [Test] + public async Task ThrowAsync_Chain() + { + var exception = new InvalidOperationException("Test"); + Func throws = () => throw exception; + Func throwsAsync = async () => { await Task.Yield(); throw exception; }; + + var chain = await throws.Should().ThrowAsync().ConfigureAwait(false); + await Assert.That(chain.Exception).IsSameReferenceAs(exception); + await Assert.That(chain.That).IsSameReferenceAs(exception); + + chain = await throwsAsync.Should().ThrowAsync().ConfigureAwait(false); + await Assert.That(chain.Exception).IsSameReferenceAs(exception); + await Assert.That(chain.That).IsSameReferenceAs(exception); + } + + [Test] + public async Task ThrowAsync_String() + { + Func doesNotThrow = () => Task.CompletedTask; + Func doesNotThrowAsync = async () => await Task.Yield(); + + var exception = new InvalidOperationException("Test"); + Func throws = () => throw exception; + Func throwsAsync = async () => { await Task.Yield(); throw exception; }; + + Func throwsWrongException = () => throw new NotSupportedException("Wrong"); + Func throwsWrongExceptionAsync = async () => { await Task.Yield(); throw new NotSupportedException("Wrong"); }; + + await Assert.That(() => throws.Should().ThrowAsync("Test")).ThrowsNothing(); + await Assert.That(() => throwsAsync.Should().ThrowAsync("Test")).ThrowsNothing(); + + await Assert.That(() => throws.Should().ThrowAsync("Wrong Message")) + .Throws().WithMessage("Value should have Message \"Wrong Message\" but was \"Test\"."); + await Assert.That(() => throwsAsync.Should().ThrowAsync("Wrong Message")) + .Throws().WithMessage("Value should have Message \"Wrong Message\" but was \"Test\"."); + + await Assert.That(() => doesNotThrow.Should().ThrowAsync("Test")) + .Throws().WithMessage("Function should throw an InvalidOperationException."); + await Assert.That(() => doesNotThrowAsync.Should().ThrowAsync("Test")) + .Throws().WithMessage("Function should throw an InvalidOperationException."); + + await Assert.That(() => throwsWrongException.Should().ThrowAsync("Test")) + .Throws().WithMessage("Function should throw an InvalidOperationException but threw a NotSupportedException with message \"Wrong\"."); + await Assert.That(() => throwsWrongExceptionAsync.Should().ThrowAsync("Test")) + .Throws().WithMessage("Function should throw an InvalidOperationException but threw a NotSupportedException with message \"Wrong\"."); + } + + [Test] + public async Task ThrowAsync_String_Chain() + { + var exception = new InvalidOperationException("Test"); + Func throws = () => throw exception; + Func throwsAsync = async () => { await Task.Yield(); throw exception; }; + + var chain = await throws.Should().ThrowAsync("Test").ConfigureAwait(false); + await Assert.That(chain.Exception).IsSameReferenceAs(exception); + await Assert.That(chain.That).IsSameReferenceAs(exception); + + chain = await throwsAsync.Should().ThrowAsync("Test").ConfigureAwait(false); + await Assert.That(chain.Exception).IsSameReferenceAs(exception); + await Assert.That(chain.That).IsSameReferenceAs(exception); + } + + [Test] + public async Task NotThrowAsync() + { + Func doesNotThrow = () => Task.CompletedTask; + Func doesNotThrowAsync = async () => await Task.Yield(); + + var exception = new InvalidOperationException("Test"); + Func throws = () => throw exception; + Func throwsAsync = async () => { await Task.Yield(); throw exception; }; + + await Assert.That(() => doesNotThrow.Should().NotThrowAsync()).ThrowsNothing(); + await Assert.That(() => doesNotThrowAsync.Should().NotThrowAsync()).ThrowsNothing(); + + var actualException = await Assert.That(() => throws.Should().NotThrowAsync()) + .Throws() + .WithMessage("Function should not throw but threw an InvalidOperationException with message \"Test\"."); + await Assert.That(actualException!.InnerException).IsSameReferenceAs(exception); + + actualException = await Assert.That(() => throwsAsync.Should().NotThrowAsync()) + .Throws() + .WithMessage("Function should not throw but threw an InvalidOperationException with message \"Test\"."); + await Assert.That(actualException!.InnerException).IsSameReferenceAs(exception); + } + + [Test] + public async Task Awaiting_InvokingExtensions() + { + var value = new TestClass(); + + await Assert.That(() => value.Awaiting(v => v.ThrowAsync()).Should().ThrowAsync()) + .ThrowsNothing(); + + await Assert.That(() => value.Awaiting(v => v.NotThrowAsync()).Should().NotThrowAsync()) + .ThrowsNothing(); + } + + [Test] + public async Task Awaiting_InvokingExtensions_WithReturn() + { + var value = new TestClass(); + + await Assert.That(() => value.Awaiting(v => v.ThrowWithReturnAsync()).Should().ThrowAsync()) + .ThrowsNothing(); + } + + private sealed class TestClass + { + public Task ThrowAsync() => throw new InvalidOperationException(); + + public async Task NotThrowAsync() => await Task.Yield(); + + public Task ThrowWithReturnAsync() => throw new InvalidOperationException(); + } +} diff --git a/src/MrKWatkins.Assertions.Tests/EnumerableAssertionsTests.cs b/src/MrKWatkins.Assertions.Tests/EnumerableAssertionsTests.cs index 4369be5..986bcd9 100644 --- a/src/MrKWatkins.Assertions.Tests/EnumerableAssertionsTests.cs +++ b/src/MrKWatkins.Assertions.Tests/EnumerableAssertionsTests.cs @@ -168,4 +168,33 @@ public async Task NotSequenceEqual_Chain() await Assert.That(chain.Value).IsEqualTo(value); await Assert.That(chain.And.Value).IsEqualTo(value); } + + [Test] + public async Task Contain_Null() + { + IEnumerable nullEnumerable = null!; + + await Assert.That(() => nullEnumerable.Should().Contain(1)).Throws() + .WithMessage("Value should not be null."); + } + + [Test] + public async Task Contain() + { + var value = new List { 1, 2, 3 }; + + await Assert.That(() => value.Should().Contain(2)).ThrowsNothing(); + await Assert.That(() => value.Should().Contain(5)).Throws() + .WithMessage("Value should contain 5 but did not."); + } + + [Test] + public async Task Contain_Chain() + { + var value = new List { 1, 2, 3 }; + + var chain = value.Should().Contain(2); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } } \ No newline at end of file diff --git a/src/MrKWatkins.Assertions.Tests/FloatingPointAssertionsTests.cs b/src/MrKWatkins.Assertions.Tests/FloatingPointAssertionsTests.cs new file mode 100644 index 0000000..1f0921b --- /dev/null +++ b/src/MrKWatkins.Assertions.Tests/FloatingPointAssertionsTests.cs @@ -0,0 +1,123 @@ +namespace MrKWatkins.Assertions.Tests; + +public sealed class FloatingPointAssertionsTests +{ + [Test] + public async Task BeApproximately() + { + const double value = 17.5; + + await Assert.That(() => value.Should().BeApproximately(17.5, 0.1)).ThrowsNothing(); + await Assert.That(() => value.Should().BeApproximately(17.45, 0.1)).ThrowsNothing(); + await Assert.That(() => value.Should().BeApproximately(17.55, 0.1)).ThrowsNothing(); + await Assert.That(() => value.Should().BeApproximately(17.6, 0.1)).Throws() + .WithMessage("Value should be approximately 17.6 (±0.1) but was 17.5."); + await Assert.That(() => value.Should().BeApproximately(17.4, 0.1)).Throws() + .WithMessage("Value should be approximately 17.4 (±0.1) but was 17.5."); + } + + [Test] + public async Task BeApproximately_Float() + { + const float value = 17.5f; + + await Assert.That(() => value.Should().BeApproximately(17.5f, 0.1f)).ThrowsNothing(); + await Assert.That(() => value.Should().BeApproximately(17.6f, 0.05f)).Throws(); + } + + [Test] + public async Task BeApproximately_Chain() + { + const double value = 17.5; + + var chain = value.Should().BeApproximately(17.5, 0.1); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } + + [Test] + public async Task BeLessThan() + { + const double value = 5.0; + + await Assert.That(() => value.Should().BeLessThan(10.0, 0.001)).ThrowsNothing(); + await Assert.That(() => value.Should().BeLessThan(5.0, 0.001)).Throws() + .WithMessage("Value should be less than 5 (±0.001) but was 5."); + await Assert.That(() => value.Should().BeLessThan(1.0, 0.001)).Throws() + .WithMessage("Value should be less than 1 (±0.001) but was 5."); + } + + [Test] + public async Task BeLessThan_Chain() + { + const double value = 5.0; + + var chain = value.Should().BeLessThan(10.0, 0.001); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } + + [Test] + public async Task BeLessThanOrEqualTo() + { + const double value = 5.0; + + await Assert.That(() => value.Should().BeLessThanOrEqualTo(10.0, 0.001)).ThrowsNothing(); + await Assert.That(() => value.Should().BeLessThanOrEqualTo(5.0, 0.001)).ThrowsNothing(); + await Assert.That(() => value.Should().BeLessThanOrEqualTo(1.0, 0.001)).Throws() + .WithMessage("Value should be less than or equal to 1 (±0.001) but was 5."); + } + + [Test] + public async Task BeLessThanOrEqualTo_Chain() + { + const double value = 5.0; + + var chain = value.Should().BeLessThanOrEqualTo(5.0, 0.001); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } + + [Test] + public async Task BeGreaterThan() + { + const double value = 5.0; + + await Assert.That(() => value.Should().BeGreaterThan(1.0, 0.001)).ThrowsNothing(); + await Assert.That(() => value.Should().BeGreaterThan(5.0, 0.001)).Throws() + .WithMessage("Value should be greater than 5 (±0.001) but was 5."); + await Assert.That(() => value.Should().BeGreaterThan(10.0, 0.001)).Throws() + .WithMessage("Value should be greater than 10 (±0.001) but was 5."); + } + + [Test] + public async Task BeGreaterThan_Chain() + { + const double value = 5.0; + + var chain = value.Should().BeGreaterThan(1.0, 0.001); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } + + [Test] + public async Task BeGreaterThanOrEqualTo() + { + const double value = 5.0; + + await Assert.That(() => value.Should().BeGreaterThanOrEqualTo(1.0, 0.001)).ThrowsNothing(); + await Assert.That(() => value.Should().BeGreaterThanOrEqualTo(5.0, 0.001)).ThrowsNothing(); + await Assert.That(() => value.Should().BeGreaterThanOrEqualTo(10.0, 0.001)).Throws() + .WithMessage("Value should be greater than or equal to 10 (±0.001) but was 5."); + } + + [Test] + public async Task BeGreaterThanOrEqualTo_Chain() + { + const double value = 5.0; + + var chain = value.Should().BeGreaterThanOrEqualTo(5.0, 0.001); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } +} diff --git a/src/MrKWatkins.Assertions.Tests/IntegerAssertionsTests.cs b/src/MrKWatkins.Assertions.Tests/IntegerAssertionsTests.cs index 028feed..8da73ae 100644 --- a/src/MrKWatkins.Assertions.Tests/IntegerAssertionsTests.cs +++ b/src/MrKWatkins.Assertions.Tests/IntegerAssertionsTests.cs @@ -270,4 +270,84 @@ public async Task ChainWithInheritedMethods() await Assert.That(() => value.Should().BePositive().And.NotEqual(0)).ThrowsNothing(); await Assert.That(() => value.Should().NotBeZero().And.Equal(42)).ThrowsNothing(); } + + [Test] + public async Task BeLessThan() + { + const int value = 5; + + await Assert.That(() => value.Should().BeLessThan(10)).ThrowsNothing(); + await Assert.That(() => value.Should().BeLessThan(5)).Throws().WithMessage("Value should be less than 5 but was 5."); + await Assert.That(() => value.Should().BeLessThan(1)).Throws().WithMessage("Value should be less than 1 but was 5."); + } + + [Test] + public async Task BeLessThan_Chain() + { + const int value = 5; + + var chain = value.Should().BeLessThan(10); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } + + [Test] + public async Task BeLessThanOrEqualTo() + { + const int value = 5; + + await Assert.That(() => value.Should().BeLessThanOrEqualTo(10)).ThrowsNothing(); + await Assert.That(() => value.Should().BeLessThanOrEqualTo(5)).ThrowsNothing(); + await Assert.That(() => value.Should().BeLessThanOrEqualTo(1)).Throws().WithMessage("Value should be less than or equal to 1 but was 5."); + } + + [Test] + public async Task BeLessThanOrEqualTo_Chain() + { + const int value = 5; + + var chain = value.Should().BeLessThanOrEqualTo(5); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } + + [Test] + public async Task BeGreaterThan() + { + const int value = 5; + + await Assert.That(() => value.Should().BeGreaterThan(1)).ThrowsNothing(); + await Assert.That(() => value.Should().BeGreaterThan(5)).Throws().WithMessage("Value should be greater than 5 but was 5."); + await Assert.That(() => value.Should().BeGreaterThan(10)).Throws().WithMessage("Value should be greater than 10 but was 5."); + } + + [Test] + public async Task BeGreaterThan_Chain() + { + const int value = 5; + + var chain = value.Should().BeGreaterThan(1); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } + + [Test] + public async Task BeGreaterThanOrEqualTo() + { + const int value = 5; + + await Assert.That(() => value.Should().BeGreaterThanOrEqualTo(1)).ThrowsNothing(); + await Assert.That(() => value.Should().BeGreaterThanOrEqualTo(5)).ThrowsNothing(); + await Assert.That(() => value.Should().BeGreaterThanOrEqualTo(10)).Throws().WithMessage("Value should be greater than or equal to 10 but was 5."); + } + + [Test] + public async Task BeGreaterThanOrEqualTo_Chain() + { + const int value = 5; + + var chain = value.Should().BeGreaterThanOrEqualTo(5); + await Assert.That(chain.Value).IsEqualTo(value); + await Assert.That(chain.And.Value).IsEqualTo(value); + } } diff --git a/src/MrKWatkins.Assertions/AsyncActionAssertions.cs b/src/MrKWatkins.Assertions/AsyncActionAssertions.cs new file mode 100644 index 0000000..845679c --- /dev/null +++ b/src/MrKWatkins.Assertions/AsyncActionAssertions.cs @@ -0,0 +1,70 @@ +namespace MrKWatkins.Assertions; + +/// +/// Provides assertions for async actions (delegates returning ), such as verifying that exceptions are thrown. +/// +/// The async action to assert on. +public sealed class AsyncActionAssertions(Func action) +{ + /// + /// Asserts that the async action throws an exception of the specified type. + /// + /// The expected exception type. + /// A that resolves to an containing the thrown exception. + public async Task> ThrowAsync() + where TException : Exception + { + TException? thrown = null; + try + { + await action().ConfigureAwait(false); + } + catch (Exception exception) + { + if (exception is not TException typedException) + { + throw Verify.CreateException($"Function should throw {Format.PrefixWithAOrAn(typeof(TException).Name)} but threw {Format.PrefixWithAOrAn(exception.GetType().Name)} with message {Format.Value(exception.Message)}.", exception); + } + thrown = typedException; + } + + if (thrown == null) + { + throw Verify.CreateException($"Function should throw {Format.PrefixWithAOrAn(typeof(TException).Name)}."); + } + + return new ActionAssertionsChain(thrown); + } + + /// + /// Asserts that the async action throws an exception of the specified type with the specified message. + /// + /// The expected exception type. + /// The expected exception message. + /// A that resolves to an containing the thrown exception. + public async Task> ThrowAsync(string expectedMessage) + where TException : Exception + { + var chain = await ThrowAsync().ConfigureAwait(false); + + chain.That.Should().HaveMessage(expectedMessage); + + return chain; + } + + /// + /// Asserts that the async action does not throw any exception. + /// + /// A that completes successfully if no exception is thrown. + public async Task NotThrowAsync() + { + try + { + await action().ConfigureAwait(false); + } + catch (Exception exception) + { + throw Verify.CreateException($"Function should not throw but threw {Format.PrefixWithAOrAn(exception.GetType().Name)} with message {Format.Value(exception.Message)}.", exception); + } + } +} diff --git a/src/MrKWatkins.Assertions/EnumerableAssertions.cs b/src/MrKWatkins.Assertions/EnumerableAssertions.cs index 9305b69..d609d8d 100644 --- a/src/MrKWatkins.Assertions/EnumerableAssertions.cs +++ b/src/MrKWatkins.Assertions/EnumerableAssertions.cs @@ -128,4 +128,18 @@ public EnumerableAssertionsChain NotSequenceEqual(params IEnumer return new EnumerableAssertionsChain(this); } + + /// + /// Asserts that the enumerable contains the specified item. + /// + /// The item that should be present in the enumerable. + /// An for chaining further assertions. + public EnumerableAssertionsChain Contain(T expected) + { + NotBeNull(); + + Verify.That(Value.Contains(expected), $"Value should contain {expected} but did not."); + + return new EnumerableAssertionsChain(this); + } } \ No newline at end of file diff --git a/src/MrKWatkins.Assertions/FloatingPointAssertions.cs b/src/MrKWatkins.Assertions/FloatingPointAssertions.cs new file mode 100644 index 0000000..0de0acc --- /dev/null +++ b/src/MrKWatkins.Assertions/FloatingPointAssertions.cs @@ -0,0 +1,77 @@ +using System.Numerics; + +namespace MrKWatkins.Assertions; + +/// +/// Provides assertions for floating-point values. +/// +/// The floating-point type of the value being asserted on. +/// The value to assert on. +public sealed class FloatingPointAssertions(T value) : ObjectAssertions(value) + where T : struct, IFloatingPoint +{ + /// + /// Asserts that the floating-point value is approximately equal to the expected value within the specified precision. + /// + /// The expected value. + /// The maximum allowed difference between the value and the expected value. + /// A for chaining further assertions. + public FloatingPointAssertionsChain BeApproximately(T expected, T precision) + { + Verify.That(T.Abs(Value - expected) <= precision, $"Value should be approximately {expected} (±{precision}) but was {Value}."); + + return new FloatingPointAssertionsChain(this); + } + + /// + /// Asserts that the floating-point value is less than the expected value. + /// + /// The value the floating-point number should be less than. + /// The precision to use for the comparison. + /// A for chaining further assertions. + public FloatingPointAssertionsChain BeLessThan(T expected, T precision) + { + Verify.That(Value < expected - precision, $"Value should be less than {expected} (±{precision}) but was {Value}."); + + return new FloatingPointAssertionsChain(this); + } + + /// + /// Asserts that the floating-point value is less than or equal to the expected value. + /// + /// The value the floating-point number should be less than or equal to. + /// The precision to use for the comparison. + /// A for chaining further assertions. + public FloatingPointAssertionsChain BeLessThanOrEqualTo(T expected, T precision) + { + Verify.That(Value <= expected + precision, $"Value should be less than or equal to {expected} (±{precision}) but was {Value}."); + + return new FloatingPointAssertionsChain(this); + } + + /// + /// Asserts that the floating-point value is greater than the expected value. + /// + /// The value the floating-point number should be greater than. + /// The precision to use for the comparison. + /// A for chaining further assertions. + public FloatingPointAssertionsChain BeGreaterThan(T expected, T precision) + { + Verify.That(Value > expected + precision, $"Value should be greater than {expected} (±{precision}) but was {Value}."); + + return new FloatingPointAssertionsChain(this); + } + + /// + /// Asserts that the floating-point value is greater than or equal to the expected value. + /// + /// The value the floating-point number should be greater than or equal to. + /// The precision to use for the comparison. + /// A for chaining further assertions. + public FloatingPointAssertionsChain BeGreaterThanOrEqualTo(T expected, T precision) + { + Verify.That(Value >= expected - precision, $"Value should be greater than or equal to {expected} (±{precision}) but was {Value}."); + + return new FloatingPointAssertionsChain(this); + } +} diff --git a/src/MrKWatkins.Assertions/FloatingPointAssertionsChain.cs b/src/MrKWatkins.Assertions/FloatingPointAssertionsChain.cs new file mode 100644 index 0000000..c73708a --- /dev/null +++ b/src/MrKWatkins.Assertions/FloatingPointAssertionsChain.cs @@ -0,0 +1,22 @@ +using System.Numerics; + +namespace MrKWatkins.Assertions; + +/// +/// Enables chaining of assertions on a floating-point value after a successful assertion. +/// +/// The floating-point type of the value being asserted on. +/// The assertions object to chain from. +public readonly struct FloatingPointAssertionsChain(FloatingPointAssertions floatingPointAssertions) + where T : struct, IFloatingPoint +{ + /// + /// Gets the assertions object for chaining further assertions. + /// + public FloatingPointAssertions And { get; } = floatingPointAssertions; + + /// + /// Gets the floating-point value being asserted on. + /// + public T Value => And.Value; +} diff --git a/src/MrKWatkins.Assertions/IntegerAssertions.cs b/src/MrKWatkins.Assertions/IntegerAssertions.cs index dc351c5..c67607c 100644 --- a/src/MrKWatkins.Assertions/IntegerAssertions.cs +++ b/src/MrKWatkins.Assertions/IntegerAssertions.cs @@ -133,4 +133,52 @@ public IntegerAssertionsChain NotBePositive() return new IntegerAssertionsChain(this); } + + /// + /// Asserts that the integer value is less than the expected value. + /// + /// The value the integer should be less than. + /// An for chaining further assertions. + public IntegerAssertionsChain BeLessThan(T expected) + { + Verify.That(Value < expected, $"Value should be less than {expected} but was {Value}."); + + return new IntegerAssertionsChain(this); + } + + /// + /// Asserts that the integer value is less than or equal to the expected value. + /// + /// The value the integer should be less than or equal to. + /// An for chaining further assertions. + public IntegerAssertionsChain BeLessThanOrEqualTo(T expected) + { + Verify.That(Value <= expected, $"Value should be less than or equal to {expected} but was {Value}."); + + return new IntegerAssertionsChain(this); + } + + /// + /// Asserts that the integer value is greater than the expected value. + /// + /// The value the integer should be greater than. + /// An for chaining further assertions. + public IntegerAssertionsChain BeGreaterThan(T expected) + { + Verify.That(Value > expected, $"Value should be greater than {expected} but was {Value}."); + + return new IntegerAssertionsChain(this); + } + + /// + /// Asserts that the integer value is greater than or equal to the expected value. + /// + /// The value the integer should be greater than or equal to. + /// An for chaining further assertions. + public IntegerAssertionsChain BeGreaterThanOrEqualTo(T expected) + { + Verify.That(Value >= expected, $"Value should be greater than or equal to {expected} but was {Value}."); + + return new IntegerAssertionsChain(this); + } } diff --git a/src/MrKWatkins.Assertions/InvokingExtensions.cs b/src/MrKWatkins.Assertions/InvokingExtensions.cs index 2a7e5cc..b70db3a 100644 --- a/src/MrKWatkins.Assertions/InvokingExtensions.cs +++ b/src/MrKWatkins.Assertions/InvokingExtensions.cs @@ -25,4 +25,25 @@ public static class InvokingExtensions /// An action that invokes the specified function with the value, for use with . [Pure] public static Action Invoking(this T value, Func action) => () => action(value); + + /// + /// Wraps an async action on the specified value for assertion testing. + /// + /// The type of the value. + /// The value to pass to the async action. + /// The async action to test. + /// A that invokes the specified async action with the value, for use with . + [Pure] + public static Func Awaiting(this T value, Func action) => () => action(value); + + /// + /// Wraps an async function on the specified value for assertion testing, discarding the return value. + /// + /// The type of the value. + /// The return type of the async function. + /// The value to pass to the async function. + /// The async function to test. + /// A that invokes the specified async function with the value, for use with . + [Pure] + public static Func Awaiting(this T value, Func> action) => () => action(value); } \ No newline at end of file diff --git a/src/MrKWatkins.Assertions/ShouldExtensions.cs b/src/MrKWatkins.Assertions/ShouldExtensions.cs index e5b05e5..dfa3685 100644 --- a/src/MrKWatkins.Assertions/ShouldExtensions.cs +++ b/src/MrKWatkins.Assertions/ShouldExtensions.cs @@ -112,6 +112,14 @@ public static ReadOnlyDictionaryAssertions, TKey, TValu [Pure] public static ActionAssertions Should([InstantHandle] this Action value) => new(value); + /// + /// Begins a fluent assertion on the specified async action. + /// + /// The async action to assert on. + /// An for the async action. + [Pure] + public static AsyncActionAssertions Should([InstantHandle] this Func value) => new(value); + /// /// Begins a fluent assertion on the specified byte value. /// @@ -201,4 +209,22 @@ public static ReadOnlyDictionaryAssertions, TKey, TValu [Pure] [OverloadResolutionPriority(10)] public static IntegerAssertions Should(this nuint value) => new(value); + + /// + /// Begins a fluent assertion on the specified float value. + /// + /// The float value to assert on. + /// A for the value. + [Pure] + [OverloadResolutionPriority(10)] + public static FloatingPointAssertions Should(this float value) => new(value); + + /// + /// Begins a fluent assertion on the specified double value. + /// + /// The double value to assert on. + /// A for the value. + [Pure] + [OverloadResolutionPriority(10)] + public static FloatingPointAssertions Should(this double value) => new(value); } \ No newline at end of file