Asp.net MVC 3 RTM Source Code 您可以从这里下载. 在源代码中有一个帮助处UnitTest中Exception的帮助类,我们还可以继续扩展。看下面的代码:
 

    public static class ExceptionAssert {
        private const string ArgumentExceptionMessageFormat = "{0}\r\nParameter name: {1}";

        public static void Throws<TException>(Action act) where TException : Exception {
            Throws<TException>(act, ex => true);
        }

        public static void Throws<TException, TResult>(Func<TResult> action) where TException : Exception
        {
            Throws<TException>(() => action(), ex => true);
        }

        public static void Throws<TException>(Action act, Func<TException,bool> condition) where TException : Exception {
            Exception ex = Capture.Exception(act);
            Assert.IsNotNull(ex, "The expected exception was not thrown");
            Assert.IsInstanceOfType(ex, typeof(TException), "The exception thrown was not of the expected type");
            Assert.IsTrue(condition((TException)ex), String.Format(@"Exception did not match the specified condition
Actual Exception: {0}", ex));
        }

        public static void Throws<TException>(Action action, string expectedMessage) where TException : Exception {
            Throws<TException>(action, ex => String.Equals(ex.Message, expectedMessage, StringComparison.Ordinal));
        }

        public static void ThrowsArgNull(Action act, string paramName) {
            Throws<ArgumentNullException>(act, CreateArgNullChecker(paramName));
        }

        public static void ThrowsArgNullOrEmpty(Action act, string paramName) {
            ThrowsArgumentException<ArgumentException>(act, paramName, CommonResources.Argument_Cannot_Be_Null_Or_Empty);
        }

        public static void ThrowsArgEmpty(Action act, string paramName) {
            ThrowsArgumentException<ArgumentException>(act, paramName, CommonResources.Argument_Must_Be_Null_Or_Non_Empty);
        }

        public static void ThrowsArgGreaterThan(Action act, string paramName, string value) {
            ThrowsArgumentException<ArgumentOutOfRangeException>(act, paramName, string.Format(CommonResources.Argument_Must_Be_GreaterThan, value));
        }

        public static void ThrowsArgGreaterThanOrEqualTo(Action act, string paramName, string value) {
            ThrowsArgumentException<ArgumentOutOfRangeException>(act, paramName, string.Format(CommonResources.Argument_Must_Be_GreaterThanOrEqualTo, value));
        }

        public static void ThrowsArgLessThan(Action act, string paramName, string value) {
            ThrowsArgumentException<ArgumentOutOfRangeException>(act, paramName, string.Format(CommonResources.Argument_Must_Be_LessThan, value));
        }

        public static void ThrowsArgLessThanOrEqualTo(Action act, string paramName, string value) {
            ThrowsArgumentException<ArgumentOutOfRangeException>(act, paramName, string.Format(CommonResources.Argument_Must_Be_LessThanOrEqualTo, value));
        }

        public static void ThrowsEnumArgOutOfRange<TEnumType>(Action act, string paramName) {
            ThrowsArgumentException<ArgumentOutOfRangeException>(act, paramName, String.Format(CommonResources.Argument_Must_Be_Enum_Member,
                                                                 typeof(TEnumType).Name));
        }

        public static void ThrowsArgOutOfRange(Action act, string paramName, object minimum, object maximum, bool equalAllowed) {
            ThrowsArgumentException<ArgumentOutOfRangeException>(act, paramName, BuildOutOfRangeMessage(paramName, minimum, maximum, equalAllowed));
        }

        internal static Func<ArgumentNullException, bool> CreateArgNullChecker(string paramName) {
            return ex => ex.ParamName.Equals(paramName);
        }

        private static string BuildOutOfRangeMessage(string paramName, object minimum, object maximum, bool equalAllowed) {
            if (minimum == null) {
                return String.Format(equalAllowed ? CommonResources.Argument_Must_Be_LessThanOrEqualTo : CommonResources.Argument_Must_Be_LessThan, maximum);
            }
            else if (maximum == null) {
                return String.Format(equalAllowed ? CommonResources.Argument_Must_Be_GreaterThanOrEqualTo : CommonResources.Argument_Must_Be_GreaterThan, minimum);
            }
            else {
                return String.Format(CommonResources.Argument_Must_Be_Between, minimum, maximum);
            }
        }

        public static void ThrowsArgumentException(Action act, string message) {
            ThrowsArgumentException<ArgumentException>(act, message);
        }

        public static void ThrowsArgumentException<TArgException>(Action act, string message) where TArgException : ArgumentException {
            Throws<TArgException>(act, ex =>
                ex.Message.Equals(message));
        }

        public static void ThrowsArgumentException(Action act, string paramName, string message) {
            ThrowsArgumentException<ArgumentException>(act, paramName, message);
        }

        public static void ThrowsArgumentException<TArgException>(Action act, string paramName, string message) where TArgException : ArgumentException {
            Throws<TArgException>(act, ex =>
                ex.ParamName.Equals(paramName) &&
                ex.Message.Equals(String.Format(ArgumentExceptionMessageFormat, message, paramName)));
        }
    }

 

public static class Capture {
    public static Exception Exception(Action act) {
        Exception ex = null;
        try {
            act();
        }
        catch (Exception exc) {
            ex = exc;
        }

        return ex;
    }
}

很有用,我们同样可以对它的UnitTest:
[TestClass]
public class ExceptionAssertTest
{
    [TestMethod]
    [ExpectedException(typeof(AssertFailedException))]
    public void DoesnotThrowException()
    {
        ExceptionAssert.Throws<ApplicationException>(() => { }, string.Empty);
    }

    [TestMethod]
    [ExpectedException(typeof(AssertFailedException))]
    public void ThrowException()
    {
        ExceptionAssert.Throws<ApplicationException>(() => { throw new ApplicationException(); }, string.Empty);
    }

    [TestMethod]
    [ExpectedException(typeof(AssertFailedException))]
    public void ThrowExceptionWithIncorrectMessage()
    {
        ExceptionAssert.Throws<ApplicationException>(() => { throw new ApplicationException("abc"); }, "cba");
    }

    [TestMethod]
    public void ThrowExceptionWithCorrectMessage()
    {
        ExceptionAssert.Throws<ApplicationException>(() => { throw new ApplicationException("abcd"); }, "abcd");
    }

    [TestMethod]
    [ExpectedException(typeof(AssertFailedException))]
    public void ThrowIncorrectException()
    {
        ExceptionAssert.Throws<ApplicationException>(() => { throw new SystemException(); }, string.Empty);
    }

    [TestMethod]
    [ExpectedException(typeof(AssertFailedException))]
    public void ThrowDerivedException()
    {
        ExceptionAssert.Throws<SystemException>(() => { throw new ArgumentException(); }, string.Empty);
    }

    [TestMethod]
    public void ExpectExceptionWithoutCheckingMessage()
    {
        ExceptionAssert.Throws<SystemException>(() => { throw new SystemException("abc"); });
    }

    public static void SimpleMethod() { throw new Exception(); }
    public static int SimpleFunction() { throw new Exception(); }

    [TestMethod]
    public void UseExpressionInsteadOfLambda()
    {
        ExceptionAssert.Throws<Exception>(SimpleMethod);
        ExceptionAssert.Throws<Exception,int>(SimpleFunction);
    }
}

在项目是它是这样用的,这样的代码是不是简洁的多:

[TestMethod]
public void ValidationSummaryClassNameThrowsWhenAssignedNull() {
    // Act and Assert
    ExceptionAssert.ThrowsArgNull(() => HtmlHelper.ValidationSummaryClass = null, "value");
}


所以任意一个流行的开源项目,都有好的代码值得我们学习. 希望对您有所帮助。

还有一个简化版本  MsTest中实现类似NUnit中Assert.Throws


作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog

posted on 2012-02-18 15:48  PetterLiu  阅读(708)  评论(0编辑  收藏  举报