Skip to content

Commit f563067

Browse files
Opens up for more control of the exception being produced (#153)
Replaces #116
1 parent 9abb929 commit f563067

File tree

6 files changed

+90
-15
lines changed

6 files changed

+90
-15
lines changed

src/projects/EnsureThat/Ensure.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@ namespace EnsureThat
77
{
88
public static class Ensure
99
{
10-
internal static readonly ExceptionFactory ExceptionFactory = new ExceptionFactory();
10+
/// <summary>
11+
/// Gets or Sets the Exception factory to use.
12+
/// </summary>
13+
public static IExceptionFactory ExceptionFactory { get; set; } = new ExceptionFactory();
1114

1215
/// <summary>
1316
/// Ensures for objects.
@@ -76,7 +79,7 @@ public static class Ensure
7679
/// <param name="optsFn"></param>
7780
/// <returns></returns>
7881
[Pure]
79-
public static Param<T> That<T>([NoEnumeration]T value, string name = null, OptsFn optsFn = null)
82+
public static Param<T> That<T>([NoEnumeration] T value, string name = null, OptsFn optsFn = null)
8083
=> new Param<T>(name, value, optsFn);
8184

8285
/// <summary>
@@ -90,7 +93,7 @@ public static Param<T> That<T>([NoEnumeration]T value, string name = null, OptsF
9093
/// <param name="optsFn"></param>
9194
/// <returns></returns>
9295
[Pure]
93-
public static StringParam That([NoEnumeration]string value, string name = null, OptsFn optsFn = null)
96+
public static StringParam That([NoEnumeration] string value, string name = null, OptsFn optsFn = null)
9497
=> new StringParam(name, value, optsFn);
9598

9699
/// <summary>
@@ -122,4 +125,4 @@ public static TypeParam ThatTypeFor<T>([NotNull] T value, string name = null, Op
122125
public static TypeParam ThatType([NotNull] Type value, string name = null, OptsFn optsFn = null)
123126
=> new TypeParam(name, value, optsFn);
124127
}
125-
}
128+
}

src/projects/EnsureThat/EnsureOptions.cs

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,42 @@
22

33
namespace EnsureThat
44
{
5+
public delegate Exception CustomExceptionFactory(string message, string paramName);
6+
57
public struct EnsureOptions
68
{
79
/// <summary>
8-
/// If defined, this exception will be thrown instead of the
9-
/// standard exceptions for the particular ensure method.
10+
/// If defined, this factory will be used to produce the exception that
11+
/// will be thrown instead of the standard exceptions for the particular
12+
/// ensure method.
13+
/// Assign using <see cref="WithExceptionFactory"/>.
14+
/// </summary>
15+
public CustomExceptionFactory CustomExceptionFactory { get; private set; }
16+
17+
/// <summary>
18+
/// If defined, and no <see cref="CustomExceptionFactory"/> has been defined,
19+
/// this exception will be thrown instead of the standard exceptions for the
20+
/// particular ensure method.
1021
/// Assign using <see cref="WithException"/>.
1122
/// </summary>
1223
public Exception CustomException { get; private set; }
1324

1425
/// <summary>
15-
/// If defined, and no <see cref="CustomException"/> has been defined,
26+
/// If defined, and neither <see cref="CustomExceptionFactory"/>
27+
/// nor <see cref="CustomException"/> has been defined,
1628
/// this message will be used instead of the standard message for the
1729
/// particular ensure method.
1830
/// Assign using <see cref="WithMessage"/>.
1931
/// </summary>
2032
public string CustomMessage { get; private set; }
2133

34+
public EnsureOptions WithExceptionFactory(CustomExceptionFactory factory)
35+
{
36+
CustomExceptionFactory = factory;
37+
38+
return this;
39+
}
40+
2241
public EnsureOptions WithException(Exception ex)
2342
{
2443
CustomException = ex;
@@ -33,4 +52,4 @@ public EnsureOptions WithMessage(string message)
3352
return this;
3453
}
3554
}
36-
}
55+
}

src/projects/EnsureThat/Internals/ExceptionFactory.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33

44
namespace EnsureThat.Internals
55
{
6-
internal sealed class ExceptionFactory
6+
internal sealed class ExceptionFactory : IExceptionFactory
77
{
88
[NotNull]
99
[Pure]
10-
internal Exception ArgumentException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null)
10+
public Exception ArgumentException(string defaultMessage, string paramName, OptsFn optsFn = null)
1111
{
1212
if (optsFn != null)
1313
{
@@ -25,12 +25,15 @@ internal Exception ArgumentException([NotNull] string defaultMessage, string par
2525

2626
[NotNull]
2727
[Pure]
28-
internal Exception ArgumentNullException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null)
28+
public Exception ArgumentNullException(string defaultMessage, string paramName, OptsFn optsFn = null)
2929
{
3030
if (optsFn != null)
3131
{
3232
var opts = optsFn(new EnsureOptions());
3333

34+
if (opts.CustomExceptionFactory != null)
35+
return opts.CustomExceptionFactory(defaultMessage, paramName);
36+
3437
if (opts.CustomException != null)
3538
return opts.CustomException;
3639

@@ -43,7 +46,7 @@ internal Exception ArgumentNullException([NotNull] string defaultMessage, string
4346

4447
[NotNull]
4548
[Pure]
46-
internal Exception ArgumentOutOfRangeException<TValue>([NotNull] string defaultMessage, string paramName, TValue value, OptsFn optsFn = null)
49+
public Exception ArgumentOutOfRangeException<TValue>(string defaultMessage, string paramName, TValue value, OptsFn optsFn = null)
4750
{
4851
if (optsFn != null)
4952
{
@@ -59,4 +62,4 @@ internal Exception ArgumentOutOfRangeException<TValue>([NotNull] string defaultM
5962
return new ArgumentOutOfRangeException(paramName, value, defaultMessage);
6063
}
6164
}
62-
}
65+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using JetBrains.Annotations;
3+
4+
namespace EnsureThat.Internals
5+
{
6+
public interface IExceptionFactory
7+
{
8+
Exception ArgumentException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null);
9+
Exception ArgumentNullException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null);
10+
Exception ArgumentOutOfRangeException<TValue>([NotNull] string defaultMessage, string paramName, TValue value, OptsFn optsFn = null);
11+
}
12+
}

src/tests/UnitTests/OptsTests.cs

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,44 @@ namespace UnitTests
1010
{
1111
public class OptsTests
1212
{
13+
public class WithCustomExceptionFactoryTests : UnitTestBase
14+
{
15+
[Fact]
16+
public void ThrowsTheCustomExceptionFromTheFactory()
17+
{
18+
object value = null;
19+
OptsFn options = o => o.WithExceptionFactory((_, __) => new KeyNotFoundException());
20+
21+
var actions = new Action[]
22+
{
23+
() => Ensure.Any.IsNotNull(value, ParamName, options),
24+
() => EnsureArg.IsNotNull(value, ParamName, options),
25+
() => Ensure.That(value, ParamName, options).IsNotNull()
26+
}.ToList();
27+
28+
actions.ForEach(a => a.Should().Throw<KeyNotFoundException>());
29+
}
30+
31+
[Fact]
32+
public void WhenWithMessageAndCustomExceptionAreSpecified_ThrowsTheCustomExceptionFromTheFactory()
33+
{
34+
object value = null;
35+
OptsFn options = o => o
36+
.WithMessage("Foo bar")
37+
.WithException(new KeyNotFoundException())
38+
.WithExceptionFactory((_, __) => new InvalidTimeZoneException());
39+
40+
var actions = new Action[]
41+
{
42+
() => Ensure.Any.IsNotNull(value, ParamName, options),
43+
() => EnsureArg.IsNotNull(value, ParamName, options),
44+
() => Ensure.That(value, ParamName,options).IsNotNull()
45+
}.ToList();
46+
47+
actions.ForEach(a => a.Should().Throw<InvalidTimeZoneException>().And.Message.Should().NotContain("Foo Bar"));
48+
}
49+
}
50+
1351
public class WithExceptionTests : UnitTestBase
1452
{
1553
[Fact]
@@ -60,4 +98,4 @@ public void ThrowsExceptionWithTheCustomMessage()
6098
}
6199
}
62100
}
63-
}
101+
}

src/tests/UnitTests/UnitTests.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFrameworks>net452;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
4+
<TargetFrameworks>net452;netcoreapp3.1;net5.0</TargetFrameworks>
55
<IsPackable>false</IsPackable>
66
<IsTestProject>true</IsTestProject>
77
</PropertyGroup>

0 commit comments

Comments
 (0)