Skip to content

Commit

Permalink
Implemented NullOrInvalidInput method (#178)
Browse files Browse the repository at this point in the history
Co-authored-by: Tiago Rios <tiagojsrios@gmail.com>
  • Loading branch information
tiagojsrios and tiagojsrios committed Jan 26, 2022
1 parent 9c271b7 commit 08c5f31
Show file tree
Hide file tree
Showing 2 changed files with 126 additions and 1 deletion.
35 changes: 34 additions & 1 deletion src/GuardClauses/GuardAgainstNullExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static T Null<T>([JetBrainsNotNull] this IGuardClause guardClause,
#else
public static T Null<T>([JetBrainsNotNull] this IGuardClause guardClause,
[NotNull, JetBrainsNotNull][ValidatedNotNull][JetBrainsNoEnumeration] T input,
[JetBrainsNotNull][CallerArgumentExpression("input")] string? parameterName = null,
[JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null,
string? message = null)
#endif
{
Expand Down Expand Up @@ -206,5 +206,38 @@ public static T Default<T>([JetBrainsNotNull] this IGuardClause guardClause,

return input;
}


/// <summary>
/// Throws an <see cref="ArgumentNullException"/> if <paramref name="input"/> is null
/// Throws an <see cref="ArgumentException" /> if <paramref name="input"/> doesn't satisfy the <paramref name="predicate"/> function.
/// </summary>
/// <param name="guardClause"></param>
/// <param name="input"></param>
/// <param name="parameterName"></param>
/// <param name="predicate"></param>
/// <param name="message">Optional. Custom error message</param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
/// <exception cref="ArgumentNullException"></exception>
#if NETSTANDARD || NETFRAMEWORK
public static T NullOrInvalidInput<T>([JetBrainsNotNull] this IGuardClause guardClause,
[JetBrainsNotNull] T input,
[JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName,
Func<T, bool> predicate,
string? message = null)
#else
public static T NullOrInvalidInput<T>([JetBrainsNotNull] this IGuardClause guardClause,
[JetBrainsNotNull] T input,
[JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName,
Func<T, bool> predicate,
string? message = null)
#endif
{
Guard.Against.Null(input, parameterName, message);

return Guard.Against.InvalidInput(input, parameterName, predicate, message);
}
}
}
92 changes: 92 additions & 0 deletions test/GuardClauses.UnitTests/GuardAgainstNullOrInvalidInput.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Ardalis.GuardClauses;
using Xunit;

namespace GuardClauses.UnitTests
{
public class GuardAgainstNullOrInvalidInput
{
[Theory]
[ClassData(typeof(ArgumentNullExceptionClassData))]
public void ThrowsArgumentNullExceptionWhenInputIsNull(string input, Func<string, bool> func)
{
Assert.Throws<ArgumentNullException>("string",
() => Guard.Against.NullOrInvalidInput(input, "string", func));
}

[Theory]
[ClassData(typeof(ArgumentExceptionClassData))]
public void ThrowsArgumentExceptionWhenInputIsInvalid(string input, Func<string, bool> func)
{
Assert.Throws<ArgumentException>("string",
() => Guard.Against.NullOrInvalidInput(input, "string", func));
}

[Theory]
[ClassData(typeof(ValidClassData))]
public void ReturnsExceptedValueWhenGivenValidInput(int input, Func<int, bool> func)
{
var result = Guard.Against.NullOrInvalidInput(input, nameof(input), func);
Assert.Equal(input, result);
}

[Theory]
[InlineData(null, "Input parameterName did not satisfy the options (Parameter 'parameterName')", typeof(ArgumentException), 10)]
[InlineData("Evaluation failed", "Evaluation failed (Parameter 'parameterName')", typeof(ArgumentException), 10)]
[InlineData(null, "Value cannot be null. (Parameter 'parameterName')", typeof(ArgumentNullException))]
[InlineData("Please provide correct value", "Please provide correct value (Parameter 'parameterName')", typeof(ArgumentNullException))]
public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage, Type exceptionType, int? input = null)
{
var exception = Assert.Throws(exceptionType,
() => Guard.Against.NullOrInvalidInput(input, "parameterName", x => x > 20, customMessage));

Assert.NotNull(exception);
Assert.NotNull(exception.Message);
Assert.Equal(expectedMessage, exception.Message);
}

[Theory]
[InlineData(null, null, typeof(ArgumentException), 10)]
[InlineData(null, "Please provide correct value", typeof(ArgumentException), 10)]
[InlineData("SomeParameter", null, typeof(ArgumentNullException))]
[InlineData("SomeOtherParameter", "Value must be correct", typeof(ArgumentNullException))]
public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage, Type exceptionType, int? input = null)
{
var exception = Assert.Throws(exceptionType,
() => Guard.Against.NullOrInvalidInput(input, expectedParamName, x => x > 20, customMessage));

Assert.IsAssignableFrom<ArgumentException>(exception);
Assert.NotNull(exception);
Assert.Equal(expectedParamName, (exception as ArgumentException)!.ParamName);
}

public class ValidClassData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { 20, (Func<int, bool>)(x => x > 10) };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

public class ArgumentNullExceptionClassData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { null, (Func<string, bool>)(x => x.Length > 10) };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

public class ArgumentExceptionClassData : IEnumerable<object[]>
{
public IEnumerator<object[]> GetEnumerator()
{
yield return new object[] { "TestData", (Func<string, bool>)(x => x.Length > 10) };
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}
}
}

0 comments on commit 08c5f31

Please sign in to comment.