Created
March 10, 2009 19:23
-
-
Save agross/77081 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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