Skip to content

Commit

Permalink
Opens up for more control of the exception being produced (#153)
Browse files Browse the repository at this point in the history
Replaces #116
  • Loading branch information
danielwertheim committed Feb 20, 2021
1 parent 9abb929 commit f563067
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 15 deletions.
11 changes: 7 additions & 4 deletions src/projects/EnsureThat/Ensure.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ namespace EnsureThat
{
public static class Ensure
{
internal static readonly ExceptionFactory ExceptionFactory = new ExceptionFactory();
/// <summary>
/// Gets or Sets the Exception factory to use.
/// </summary>
public static IExceptionFactory ExceptionFactory { get; set; } = new ExceptionFactory();

/// <summary>
/// Ensures for objects.
Expand Down Expand Up @@ -76,7 +79,7 @@ public static class Ensure
/// <param name="optsFn"></param>
/// <returns></returns>
[Pure]
public static Param<T> That<T>([NoEnumeration]T value, string name = null, OptsFn optsFn = null)
public static Param<T> That<T>([NoEnumeration] T value, string name = null, OptsFn optsFn = null)
=> new Param<T>(name, value, optsFn);

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

/// <summary>
Expand Down Expand Up @@ -122,4 +125,4 @@ public static TypeParam ThatTypeFor<T>([NotNull] T value, string name = null, Op
public static TypeParam ThatType([NotNull] Type value, string name = null, OptsFn optsFn = null)
=> new TypeParam(name, value, optsFn);
}
}
}
27 changes: 23 additions & 4 deletions src/projects/EnsureThat/EnsureOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,42 @@

namespace EnsureThat
{
public delegate Exception CustomExceptionFactory(string message, string paramName);

public struct EnsureOptions
{
/// <summary>
/// If defined, this exception will be thrown instead of the
/// standard exceptions for the particular ensure method.
/// If defined, this factory will be used to produce the exception that
/// will be thrown instead of the standard exceptions for the particular
/// ensure method.
/// Assign using <see cref="WithExceptionFactory"/>.
/// </summary>
public CustomExceptionFactory CustomExceptionFactory { get; private set; }

/// <summary>
/// If defined, and no <see cref="CustomExceptionFactory"/> has been defined,
/// this exception will be thrown instead of the standard exceptions for the
/// particular ensure method.
/// Assign using <see cref="WithException"/>.
/// </summary>
public Exception CustomException { get; private set; }

/// <summary>
/// If defined, and no <see cref="CustomException"/> has been defined,
/// If defined, and neither <see cref="CustomExceptionFactory"/>
/// nor <see cref="CustomException"/> has been defined,
/// this message will be used instead of the standard message for the
/// particular ensure method.
/// Assign using <see cref="WithMessage"/>.
/// </summary>
public string CustomMessage { get; private set; }

public EnsureOptions WithExceptionFactory(CustomExceptionFactory factory)
{
CustomExceptionFactory = factory;

return this;
}

public EnsureOptions WithException(Exception ex)
{
CustomException = ex;
Expand All @@ -33,4 +52,4 @@ public EnsureOptions WithMessage(string message)
return this;
}
}
}
}
13 changes: 8 additions & 5 deletions src/projects/EnsureThat/Internals/ExceptionFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

namespace EnsureThat.Internals
{
internal sealed class ExceptionFactory
internal sealed class ExceptionFactory : IExceptionFactory
{
[NotNull]
[Pure]
internal Exception ArgumentException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null)
public Exception ArgumentException(string defaultMessage, string paramName, OptsFn optsFn = null)
{
if (optsFn != null)
{
Expand All @@ -25,12 +25,15 @@ internal Exception ArgumentException([NotNull] string defaultMessage, string par

[NotNull]
[Pure]
internal Exception ArgumentNullException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null)
public Exception ArgumentNullException(string defaultMessage, string paramName, OptsFn optsFn = null)
{
if (optsFn != null)
{
var opts = optsFn(new EnsureOptions());

if (opts.CustomExceptionFactory != null)
return opts.CustomExceptionFactory(defaultMessage, paramName);

if (opts.CustomException != null)
return opts.CustomException;

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

[NotNull]
[Pure]
internal Exception ArgumentOutOfRangeException<TValue>([NotNull] string defaultMessage, string paramName, TValue value, OptsFn optsFn = null)
public Exception ArgumentOutOfRangeException<TValue>(string defaultMessage, string paramName, TValue value, OptsFn optsFn = null)
{
if (optsFn != null)
{
Expand All @@ -59,4 +62,4 @@ internal Exception ArgumentOutOfRangeException<TValue>([NotNull] string defaultM
return new ArgumentOutOfRangeException(paramName, value, defaultMessage);
}
}
}
}
12 changes: 12 additions & 0 deletions src/projects/EnsureThat/Internals/IExceptionFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using JetBrains.Annotations;

namespace EnsureThat.Internals
{
public interface IExceptionFactory
{
Exception ArgumentException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null);
Exception ArgumentNullException([NotNull] string defaultMessage, string paramName, OptsFn optsFn = null);
Exception ArgumentOutOfRangeException<TValue>([NotNull] string defaultMessage, string paramName, TValue value, OptsFn optsFn = null);
}
}
40 changes: 39 additions & 1 deletion src/tests/UnitTests/OptsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,44 @@ namespace UnitTests
{
public class OptsTests
{
public class WithCustomExceptionFactoryTests : UnitTestBase
{
[Fact]
public void ThrowsTheCustomExceptionFromTheFactory()
{
object value = null;
OptsFn options = o => o.WithExceptionFactory((_, __) => new KeyNotFoundException());

var actions = new Action[]
{
() => Ensure.Any.IsNotNull(value, ParamName, options),
() => EnsureArg.IsNotNull(value, ParamName, options),
() => Ensure.That(value, ParamName, options).IsNotNull()
}.ToList();

actions.ForEach(a => a.Should().Throw<KeyNotFoundException>());
}

[Fact]
public void WhenWithMessageAndCustomExceptionAreSpecified_ThrowsTheCustomExceptionFromTheFactory()
{
object value = null;
OptsFn options = o => o
.WithMessage("Foo bar")
.WithException(new KeyNotFoundException())
.WithExceptionFactory((_, __) => new InvalidTimeZoneException());

var actions = new Action[]
{
() => Ensure.Any.IsNotNull(value, ParamName, options),
() => EnsureArg.IsNotNull(value, ParamName, options),
() => Ensure.That(value, ParamName,options).IsNotNull()
}.ToList();

actions.ForEach(a => a.Should().Throw<InvalidTimeZoneException>().And.Message.Should().NotContain("Foo Bar"));
}
}

public class WithExceptionTests : UnitTestBase
{
[Fact]
Expand Down Expand Up @@ -60,4 +98,4 @@ public void ThrowsExceptionWithTheCustomMessage()
}
}
}
}
}
2 changes: 1 addition & 1 deletion src/tests/UnitTests/UnitTests.csproj
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net452;netcoreapp2.1;netcoreapp3.1;net5.0</TargetFrameworks>
<TargetFrameworks>net452;netcoreapp3.1;net5.0</TargetFrameworks>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
Expand Down

0 comments on commit f563067

Please sign in to comment.