Skip to content

Instantly share code, notes, and snippets.

@agross
Created March 10, 2009 19:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save agross/77081 to your computer and use it in GitHub Desktop.
Save agross/77081 to your computer and use it in GitHub Desktop.
using System;
using Indigo.ForTesting;
using Machine.Specifications;
namespace Indigo.Tools.Tests
{
[Behaviors]
public class ArgumentNullExceptionBehavior
{
protected static Exception Exception;
It should_throw_an_ArgumentNullException = () => Exception.ShouldBeOfType<ArgumentNullException>();
It should_set_the_parameter_name = () => Exception.As<ArgumentNullException>().ParamName.ShouldEqual("arg");
}
[Behaviors]
public class ArgumentExceptionBehavior
{
protected static Exception Exception;
It should_throw_an_ArgumentException = () => Exception.ShouldBeOfType<ArgumentException>();
It should_set_the_parameter_name = () => Exception.As<ArgumentException>().ParamName.ShouldEqual("arg");
It should_set_the_message = () => Exception.Message.ShouldContain("message");
}
[Subject(typeof(Ensure))]
public class When_a_null_argument_is_tested_for_nullity
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg").IsNotNull((object) null));
Behaves_like<ArgumentNullExceptionBehavior> failing_with_ArgumentNullException;
}
[Subject(typeof(Ensure))]
public class When_a_not_null_argument_is_tested_for_nullity
{
Because of = () => Ensure.Argument("arg").IsNotNull(new object());
It should_not_throw_a_exception = () => true.ShouldBeTrue();
}
[Subject(typeof(Ensure))]
public class When_a_null_reference_type_argument_is_tested_for_nullity_or_the_default_value
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg").IsNotNullOrDefault((object) null));
Behaves_like<ArgumentNullExceptionBehavior> failing_with_ArgumentNullException;
}
[Subject(typeof(Ensure))]
public class When_a_not_null_reference_type_argument_is_tested_for_nullity_or_the_default_value
{
Because of = () => Ensure.Argument("arg").IsNotNullOrDefault(new object());
It should_not_throw_a_exception = () => true.ShouldBeTrue();
}
[Subject(typeof(Ensure))]
public class When_an_uninitialized_value_type_argument_is_tested_for_nullity_or_the_default_value
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg").IsNotNullOrDefault(0));
Behaves_like<ArgumentNullExceptionBehavior> failing_with_ArgumentNullException;
}
[Subject(typeof(Ensure))]
public class When_an_initialized_value_type_argument_is_tested_for_nullity_or_the_default_value
{
Because of = () => Ensure.Argument("arg").IsNotNullOrDefault(42);
It should_not_throw_a_exception = () => true.ShouldBeTrue();
}
[Subject(typeof(Ensure))]
public class When_a_null_reference_type_argument_is_tested_for_the_default_value
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg").IsNotDefault((object) null, "message"));
Behaves_like<ArgumentExceptionBehavior> failing_with_ArgumentException;
}
[Subject(typeof(Ensure))]
public class When_a_not_null_reference_type_argument_is_tested_for_the_default_value
{
Because of = () => Ensure.Argument("arg").IsNotDefault(new object(), "message");
It should_not_throw_a_exception = () => true.ShouldBeTrue();
}
[Subject(typeof(Ensure))]
public class When_an_uninitialized_value_type_argument_is_tested_for_the_default_value
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg").IsNotDefault(0, "message"));
Behaves_like<ArgumentExceptionBehavior> failing_with_ArgumentException;
}
[Subject(typeof(Ensure))]
public class When_an_initialized_value_type_argument_is_tested_for_the_default_value
{
Because of = () => Ensure.Argument("arg").IsNotDefault(42, "message");
It should_not_throw_a_exception = () => true.ShouldBeTrue();
}
[Subject(typeof(Ensure))]
public class When_a_null_string_is_tested_for_emptiness
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg").IsNotNullOrEmptyString(null, "message"));
Behaves_like<ArgumentNullExceptionBehavior> failing_with_ArgumentNullException;
}
[Subject(typeof(Ensure))]
public class When_an_empty_string_is_tested_for_emptiness
{
protected static Exception Exception;
Because of =
() => Exception = Catch.Exception(() => Ensure.Argument("arg").IsNotNullOrEmptyString(String.Empty, "message"));
Behaves_like<ArgumentExceptionBehavior> failing_with_ArgumentException;
}
[Subject(typeof(Ensure))]
public class When_a_not_null_string_is_tested_for_emptiness
{
Because of = () => Ensure.Argument("arg").IsNotNullOrEmptyString("foo", "message");
It should_not_throw_a_exception = () => true.ShouldBeTrue();
}
[Subject(typeof(Ensure))]
public class When_an_invalid_argument_is_ensured_with_custom_logic
{
static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg")
.Satisfies(false)
.With<InvalidOperationException>("message"));
It should_throw_an_exception_of_the_specified_type = () => Exception.ShouldBeOfType<InvalidOperationException>();
It should_set_the_message = () => Exception.Message.ShouldEqual("message");
}
[Subject(typeof(Ensure))]
public class When_an_invalid_argument_is_ensured_with_custom_logic_without_giving_a_custom_exception
{
static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg").Satisfies(false));
It should_not_throw_an_exception = () => Exception.ShouldBeNull();
}
[Subject(typeof(Ensure))]
public class When_an_invalid_argument_is_validated_with_custom_logic_and_ArgumentException
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg")
.Satisfies(false)
.With<ArgumentException>("message"));
Behaves_like<ArgumentExceptionBehavior> failing_with_ArgumentException;
}
[Subject(typeof(Ensure))]
public class When_an_invalid_argument_is_validated_with_custom_logic_and_ArgumentNullException
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg")
.Satisfies(false)
.With<ArgumentNullException>("message"));
Behaves_like<ArgumentNullExceptionBehavior> failing_with_ArgumentNullException;
}
[Subject(typeof(Ensure))]
public class When_an_invalid_argument_is_validated_with_custom_logic_and_ArgumentOutOfRangeException
{
static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure.Argument("arg")
.Satisfies(false)
.With<ArgumentOutOfRangeException>("message"));
It should_throw_an_exception_of_the_specified_type = () => Exception.ShouldBeOfType<ArgumentOutOfRangeException>();
It should_set_the_offending_parameter_name =
() => Exception.As<ArgumentOutOfRangeException>().ParamName.ShouldEqual("arg");
It should_set_the_message = () => Exception.Message.ShouldContain("message");
}
[Subject(typeof(Ensure))]
public class When_a_valid_argument_is_validated_with_custom_logic
{
Because of = () => Ensure.Argument("arg")
.Satisfies(true)
.With<InvalidOperationException>("message");
It should_not_throw_a_exception = () => true.ShouldBeTrue();
}
[Subject(typeof(Ensure))]
public class When_the_argument_name_is_derived_from_a_property_of_a_reference_type
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure
.Property<Foo>(x => x.Bar)
.Satisfies(false)
.With<ArgumentNullException>(null));
Behaves_like<ArgumentFromPropertyNameBehavior> failing_with_property_name;
class Foo
{
public string Bar
{
get;
set;
}
}
}
[Subject(typeof(Ensure))]
public class When_the_argument_name_is_derived_from_a_property_of_a_structure_type
{
protected static Exception Exception;
Because of = () => Exception = Catch.Exception(() => Ensure
.Property<Foo>(x => x.Bar)
.Satisfies(false)
.With<ArgumentNullException>(null));
Behaves_like<ArgumentFromPropertyNameBehavior> failing_with_property_name;
class Foo
{
public TimeSpan Bar
{
get;
set;
}
}
}
[Behaviors]
public class ArgumentFromPropertyNameBehavior
{
protected static Exception Exception;
It should_throw_an_ArgumentNullException = () => Exception.ShouldBeOfType<ArgumentNullException>();
It should_set_the_parameter_name = () => Exception.As<ArgumentNullException>().ParamName.ShouldEqual("Bar");
}
}
using System;
using System.Linq.Expressions;
namespace Indigo.Tools
{
public static class Ensure
{
public static ThrowingValidator Argument(string argument)
{
return new ThrowingValidator(argument);
}
public static ThrowingValidator Property<T>(Expression<Func<T, object>> property)
{
MemberExpression memberExpression = null;
if (property.Body.NodeType == ExpressionType.Convert)
{
UnaryExpression body = (UnaryExpression)property.Body;
memberExpression = body.Operand as MemberExpression;
}
else if (property.Body.NodeType == ExpressionType.MemberAccess)
{
memberExpression = property.Body as MemberExpression;
}
if (memberExpression == null)
{
throw new ArgumentException("Not a member access", "property");
}
return new ThrowingValidator(memberExpression.Member.Name);
}
}
}
using System;
namespace Indigo.Tools
{
public class ThrowingValidator
{
readonly string _argumentOrPropertyName;
bool _assertion = true;
internal ThrowingValidator(string argumentOrPropertyName)
{
_argumentOrPropertyName = argumentOrPropertyName;
}
public ThrowHelper Satisfies(bool assertion)
{
return new ThrowHelper(_argumentOrPropertyName, assertion);
}
/// <summary>
/// Helper method which throws an <see cref="ArgumentNullException"/> if the specified value is <c>null</c>.
/// </summary>
/// <typeparam name="T">The type of the argument.</typeparam>
/// <param name="value">The value to check.</param>
/// <exception cref="T:System.ArgumentNullException">
/// Thrown when <paramref name="value"/> is <c>null</c>.
/// </exception>
public void IsNotNull<T>(T value)
{
_assertion = value != null;
With<ArgumentNullException>(null);
}
/// <summary>
/// Helper method which throws an <see cref="ArgumentNullException" /> if the specified value is <c>null</c> or zero.
/// </summary>
/// <typeparam name="T">The type of the argument.</typeparam>
/// <param name="value">The value to check.</param>
/// <exception cref="T:System.ArgumentNullException">
/// Thrown when <paramref name="value"/> is <c>null</c> or zero.
/// </exception>
public void IsNotNullOrDefault<T>(T value)
{
_assertion = !(value == null || Equals(value, default(T)));
With<ArgumentNullException>(null);
}
/// <summary>
/// Helper method which throws an <see cref="ArgumentException"/> if the specified value is uninitialized (meaning holding
/// the default value).
/// </summary>
/// <param name="value">The value.</param>
/// <param name="message">The name of the argument which is checked.</param>
/// <exception cref="T:System.ArgumentException">
/// Thrown when <paramref message="value"/> is <c>null</c> for reference types, or zero for value types.
/// </exception>
public void IsNotDefault<T>(T value, string message)
{
_assertion = !(Equals(value, default(T)) && !typeof(T).IsEnum);
With<ArgumentException>(message);
}
/// <summary>
/// Checks a string argument to ensure it isn't null or empty.
/// </summary>
/// <param name="value">The argument value to check.</param>
/// <param name="message">The name of the argument (if the argument is null) or the message (if the argument string is
/// empty).</param>
/// <exception cref="T:System.ArgumentNullException">
/// Thrown when <paramref message="value"/> is <c>null</c>.
/// </exception>
/// <exception cref="T:System.ArgumentException">
/// Thrown when <paramref message="value"/> contains an empty
/// <see cref="string"/>.
/// </exception>
public void IsNotNullOrEmptyString(string value, string message)
{
_assertion = !String.IsNullOrEmpty(value);
With<ArgumentNullException>(message);
}
void With<TExceptionToThrow>(string message) where TExceptionToThrow : Exception
{
new ThrowHelper(_argumentOrPropertyName, _assertion).With<TExceptionToThrow>(message);
}
#region Nested type: ThrowHelper
public class ThrowHelper
{
readonly string _argumentOrPropertyName;
readonly bool _assertion;
internal ThrowHelper(string argumentOrPropertyName, bool assertion)
{
_argumentOrPropertyName = argumentOrPropertyName;
_assertion = assertion;
}
public void With<TExceptionToThrow>(string message) where TExceptionToThrow : Exception
{
ValidatePreCondition<TExceptionToThrow>(message);
}
void ValidatePreCondition<TExceptionToThrow>(string message) where TExceptionToThrow : Exception
{
if (_assertion)
{
return;
}
if (typeof(TExceptionToThrow) == typeof(ArgumentException))
{
throw (TExceptionToThrow) Activator.CreateInstance(typeof(TExceptionToThrow),
message,
_argumentOrPropertyName);
}
if (typeof(TExceptionToThrow) == typeof(ArgumentNullException) ||
typeof(TExceptionToThrow) == typeof(ArgumentOutOfRangeException))
{
throw (TExceptionToThrow) Activator.CreateInstance(typeof(TExceptionToThrow),
_argumentOrPropertyName,
message ?? String.Empty);
}
throw (TExceptionToThrow) Activator.CreateInstance(typeof(TExceptionToThrow), message);
}
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment