I have still another version of my validation extensions. I've reworked it and added some new features. It doesn't relay on expression trees any more but as a compensation the same extensions can be used for unit testing.The base class is still the ValidationContext:public class ValidationContext<TArg>{    private string _memberName;    public TArg Argument { get; internal set; }    public string MemberName    {        get        {            if (!string.IsNullOrEmpty(_memberName)) return _memberName;            var memberExpression = Expression().Body as MemberExpression;            return memberExpression.Member.Name;        }        set { _memberName = value; }    }    internal Func<Expression<Func<TArg>>> Expression { get; set; }    public virtual ValidationContext<TArg> Validate<TException>(        Func<TArg, bool> predicate,         params object[] args)         where TException : Exception    {        if (!predicate(Argument))        {            throw (TException)Activator.CreateInstance(typeof(TException), args);        }        return this;    }}however in this version it is the one that throws exceptions after checking a  validation rule. The Validate method can be overriden in a derived class which allows to create a new validation context for unit testing. It is now able to throw a different kind of exception that the unit testing environment will notice. It forwards the original exception as the inner one.public class UnitTestingValidationContext<TArg> : ValidationContext<TArg>{    public override ValidationContext<TArg> Validate<TException>(        Func<TArg, bool> predicate,         params object[] args)    {        try        {            if (!predicate(Argument))            {                throw (TException)Activator.CreateInstance(typeof(TException), args);            }            return this;        }        catch (Exception inner)        {            // cannot throw this in linqpad            //throw new AssertFailedException            throw new Exception(This is a test., inner);        }    }}As a result the Validations extensions have changed a little and have gotten a new Test method and refactored validations:public static class Validations{    // crates validation context for normal usage    public static ValidationContext<TArg> Validate<TArg>(        this TArg arg,         string memberName)    {        return new ValidationContext<TArg>()        {            Argument = arg,            MemberName = memberName        };    }    // create validation context for unit-testing    public static UnitTestingValidationContext<TArg> Test<TArg>(        this TArg arg,         string memberName)    {        return new UnitTestingValidationContext<TArg>()        {            Argument = arg,            MemberName = memberName        };    }    // validations don't throw exceptions anymore but tell the context how to do it    public static ValidationContext<TArg> IsNotNull<TArg>(        this ValidationContext<TArg> context)    {        return context.Validate<ArgumentNullException>(arg =>             arg != null, context.MemberName, Test message.);    }    public static ValidationContext<string> IsNotNullOrEmpty(        this ValidationContext<string> context)    {        return context.Validate<ArgumentNullException>(arg =>             !string.IsNullOrEmpty(context.Argument), context.MemberName, Test message.);    }}Examples:var foo = (string)null;// normal usage like for method parameters etc.foo.Validate(foo).IsNotNullOrEmpty(); // bam!// in unit-testingfoo.Test(foo).IsNotNullOrEmpty(); // bam!Some more examples showing how I mean to use the extensions (this is a special case where I wrap the validation in an Action because it looks nice when alls tests look the same):[TestMethod]public void IsNullPasses(){   new Action(() => ((string)null).Validate().IsNull()).Test().DoesNotThrow();}[TestMethod]public void IsNullThrows(){    new Action(() => .Validate().IsNull()).Test().Throws<ArgumentException>();}
Validation extensions v2
c#;unit testing;validation;extension methods;framework
I wasn't happy with the above solution so I've refactored it a little bit to get this:The validation context had too many resposibilities so it has lost its Validate method:public class ValidationContext<TArg>{    public ValidationContext(TArg argument, string memberName)    {        Argument = argument;        MemberName = memberName;    }    public TArg Argument { get; }    public string MemberName { get; }}Instead I created a Validation class that stores the result and if necessary throws an exception:public class Validation<T>{    public Validation(ValidationContext<T> context, bool success)    {        Context = context;        Success = success;    }    public ValidationContext<T> Context { get; }    public bool Success { get; set; }    public ValidationContext<T> Throw<TException>(Func<ValidationContext<T>, string> getMessage) where TException : Exception    {        if (Success)        {            return Context;        }        var message = getMessage(Context)?.Format(Context);        throw (TException)Activator.CreateInstance(typeof(TException), message);    }}and a validation builder that executes the validation and return the result as Validation object:public static class ValidationBuilder{    public static Validation<TArg> If<TArg>(this ValidationContext<TArg> context, Func<TArg, bool> predicate)    {        return new Validation<TArg>(context, predicate(context.Argument));    }}Its usage didn't change much:public static ValidationContext<TArg> IsNotNull<TArg>(    this ValidationContext<TArg> context, Func<ValidationContext<TArg>,    string> getMessage = null){    return context        .If(arg => arg == null)        .Throw<ValidationException>(            getMessage ?? (ctx => $'{ctx.MemberName}' must not be null.));}and a real-world usage example:public static bool IsStatic(this Type type){    type.Validate(nameof(type)).IsNotNull();    return type.IsAbstract && type.IsSealed;}