Skip to content

Commit 08c5f31

Browse files
authored
Implemented NullOrInvalidInput method (#178)
Co-authored-by: Tiago Rios <tiagojsrios@gmail.com>
1 parent 9c271b7 commit 08c5f31

File tree

2 files changed

+126
-1
lines changed

2 files changed

+126
-1
lines changed

src/GuardClauses/GuardAgainstNullExtensions.cs

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static T Null<T>([JetBrainsNotNull] this IGuardClause guardClause,
3434
#else
3535
public static T Null<T>([JetBrainsNotNull] this IGuardClause guardClause,
3636
[NotNull, JetBrainsNotNull][ValidatedNotNull][JetBrainsNoEnumeration] T input,
37-
[JetBrainsNotNull][CallerArgumentExpression("input")] string? parameterName = null,
37+
[JetBrainsNotNull][JetBrainsInvokerParameterName][CallerArgumentExpression("input")] string? parameterName = null,
3838
string? message = null)
3939
#endif
4040
{
@@ -206,5 +206,38 @@ public static T Default<T>([JetBrainsNotNull] this IGuardClause guardClause,
206206

207207
return input;
208208
}
209+
210+
211+
/// <summary>
212+
/// Throws an <see cref="ArgumentNullException"/> if <paramref name="input"/> is null
213+
/// Throws an <see cref="ArgumentException" /> if <paramref name="input"/> doesn't satisfy the <paramref name="predicate"/> function.
214+
/// </summary>
215+
/// <param name="guardClause"></param>
216+
/// <param name="input"></param>
217+
/// <param name="parameterName"></param>
218+
/// <param name="predicate"></param>
219+
/// <param name="message">Optional. Custom error message</param>
220+
/// <typeparam name="T"></typeparam>
221+
/// <returns></returns>
222+
/// <exception cref="ArgumentException"></exception>
223+
/// <exception cref="ArgumentNullException"></exception>
224+
#if NETSTANDARD || NETFRAMEWORK
225+
public static T NullOrInvalidInput<T>([JetBrainsNotNull] this IGuardClause guardClause,
226+
[JetBrainsNotNull] T input,
227+
[JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName,
228+
Func<T, bool> predicate,
229+
string? message = null)
230+
#else
231+
public static T NullOrInvalidInput<T>([JetBrainsNotNull] this IGuardClause guardClause,
232+
[JetBrainsNotNull] T input,
233+
[JetBrainsNotNull][JetBrainsInvokerParameterName] string parameterName,
234+
Func<T, bool> predicate,
235+
string? message = null)
236+
#endif
237+
{
238+
Guard.Against.Null(input, parameterName, message);
239+
240+
return Guard.Against.InvalidInput(input, parameterName, predicate, message);
241+
}
209242
}
210243
}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using Ardalis.GuardClauses;
5+
using Xunit;
6+
7+
namespace GuardClauses.UnitTests
8+
{
9+
public class GuardAgainstNullOrInvalidInput
10+
{
11+
[Theory]
12+
[ClassData(typeof(ArgumentNullExceptionClassData))]
13+
public void ThrowsArgumentNullExceptionWhenInputIsNull(string input, Func<string, bool> func)
14+
{
15+
Assert.Throws<ArgumentNullException>("string",
16+
() => Guard.Against.NullOrInvalidInput(input, "string", func));
17+
}
18+
19+
[Theory]
20+
[ClassData(typeof(ArgumentExceptionClassData))]
21+
public void ThrowsArgumentExceptionWhenInputIsInvalid(string input, Func<string, bool> func)
22+
{
23+
Assert.Throws<ArgumentException>("string",
24+
() => Guard.Against.NullOrInvalidInput(input, "string", func));
25+
}
26+
27+
[Theory]
28+
[ClassData(typeof(ValidClassData))]
29+
public void ReturnsExceptedValueWhenGivenValidInput(int input, Func<int, bool> func)
30+
{
31+
var result = Guard.Against.NullOrInvalidInput(input, nameof(input), func);
32+
Assert.Equal(input, result);
33+
}
34+
35+
[Theory]
36+
[InlineData(null, "Input parameterName did not satisfy the options (Parameter 'parameterName')", typeof(ArgumentException), 10)]
37+
[InlineData("Evaluation failed", "Evaluation failed (Parameter 'parameterName')", typeof(ArgumentException), 10)]
38+
[InlineData(null, "Value cannot be null. (Parameter 'parameterName')", typeof(ArgumentNullException))]
39+
[InlineData("Please provide correct value", "Please provide correct value (Parameter 'parameterName')", typeof(ArgumentNullException))]
40+
public void ErrorMessageMatchesExpected(string customMessage, string expectedMessage, Type exceptionType, int? input = null)
41+
{
42+
var exception = Assert.Throws(exceptionType,
43+
() => Guard.Against.NullOrInvalidInput(input, "parameterName", x => x > 20, customMessage));
44+
45+
Assert.NotNull(exception);
46+
Assert.NotNull(exception.Message);
47+
Assert.Equal(expectedMessage, exception.Message);
48+
}
49+
50+
[Theory]
51+
[InlineData(null, null, typeof(ArgumentException), 10)]
52+
[InlineData(null, "Please provide correct value", typeof(ArgumentException), 10)]
53+
[InlineData("SomeParameter", null, typeof(ArgumentNullException))]
54+
[InlineData("SomeOtherParameter", "Value must be correct", typeof(ArgumentNullException))]
55+
public void ExceptionParamNameMatchesExpected(string expectedParamName, string customMessage, Type exceptionType, int? input = null)
56+
{
57+
var exception = Assert.Throws(exceptionType,
58+
() => Guard.Against.NullOrInvalidInput(input, expectedParamName, x => x > 20, customMessage));
59+
60+
Assert.IsAssignableFrom<ArgumentException>(exception);
61+
Assert.NotNull(exception);
62+
Assert.Equal(expectedParamName, (exception as ArgumentException)!.ParamName);
63+
}
64+
65+
public class ValidClassData : IEnumerable<object[]>
66+
{
67+
public IEnumerator<object[]> GetEnumerator()
68+
{
69+
yield return new object[] { 20, (Func<int, bool>)(x => x > 10) };
70+
}
71+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
72+
}
73+
74+
public class ArgumentNullExceptionClassData : IEnumerable<object[]>
75+
{
76+
public IEnumerator<object[]> GetEnumerator()
77+
{
78+
yield return new object[] { null, (Func<string, bool>)(x => x.Length > 10) };
79+
}
80+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
81+
}
82+
83+
public class ArgumentExceptionClassData : IEnumerable<object[]>
84+
{
85+
public IEnumerator<object[]> GetEnumerator()
86+
{
87+
yield return new object[] { "TestData", (Func<string, bool>)(x => x.Length > 10) };
88+
}
89+
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
90+
}
91+
}
92+
}

0 commit comments

Comments
 (0)