【问题标题】:MSTest Test Context Exception HandlingMSTest 测试上下文异常处理
【发布时间】:2010-01-14 16:33:34
【问题描述】:

有没有一种方法可以让我使用 TestContext 或基础测试类上的其他方法来处理 MSTest 框架处理的异常?

如果在我的一个测试中发生未处理的异常,我想遍历异常中的所有项目。数据字典并将它们显示到测试结果中,以帮助我找出测试失败的原因(我们通常添加数据到异常以帮助我们在生产环境中调试,所以我想为测试做同样的事情)。

注意:我没有测试应该发生的异常(我有其他测试),我正在测试一个有效的案例,我只需要查看异常数据。

这是我正在谈论的代码示例。

[TestMethod]
public void IsFinanceDeadlineDateValid()
{
    var target = new BusinessObject();
    SetupBusinessObject(target);

    //How can I capture this in the text context so I can display all the data 
    //in the exception in the test result...

    var expected = 100;
    try
    {
        Assert.AreEqual(expected, target.PerformSomeCalculationThatMayDivideByZero());
    }
    catch (Exception ex)
    {
        ex.Data.Add("SomethingImportant", "I want to see this in the test result, as its important");
        ex.Data.Add("Expected", expected);
        throw ex;
    }

}

我知道为什么我可能不应该有这样的封装方法存在一些问题,但我们也有子测试来测试 PerformSomeCalculation 的所有功能......

但是,如果测试失败,99% 的情况下,我重新运行它都会通过,所以如果没有这些信息,我将无法调试任何东西。我还想在 GLOBAL 级别上执行此操作,以便如果任何测试失败,我会在测试结果中获取信息,而不是为每个单独的测试执行此操作。

这是将异常信息放入测试结果的代码。

    public void AddDataFromExceptionToResults(Exception ex)
    {
        StringBuilder whereAmI = new StringBuilder();
        var holdException = ex;
        while (holdException != null)
        {
            Console.WriteLine(whereAmI.ToString() + "--" + holdException.Message);
            foreach (var item in holdException.Data.Keys)
            {
                Console.WriteLine(whereAmI.ToString() + "--Data--" + item + ":" + holdException.Data[item]);
            }

            holdException = holdException.InnerException;
        }
    }

【问题讨论】:

标签: c# unit-testing exception-handling mstest


【解决方案1】:

我遇到了同样的问题,似乎没有对此的支持。你甚至不能使用 ApplicationDomain 的未处理异常挂钩,因为如果 MSTEST 在异常冒出这么远之前没有捕获它们,它本身就会崩溃。

可能的解决方法:

    private delegate void TestImplDelegate();

    private void RunTestWithExceptionLogging(TestImplDelegate testImpl)
    {
        try
        {
            testImpl();
        }
        catch (Exception e)
        {
            string message = e.Message; // don't warn about unused variables

            // do logging here
        }
    }

    [TestMethod]
    public void test1()
    {
        RunTestWithExceptionLogging(test1Impl);
    }
    private void test1Impl()
    {
        // test code goes here

        throw new Exception("This should get logged by the test wrapper.");
    }

    [TestMethod]
    public void test2()
    {
        RunTestWithExceptionLogging(test2Impl);
    }
    private void test2Impl()
    {
        // test code goes here

        throw new Exception("This should get logged by the test wrapper.");
    }

这当然不是最佳的,但至少这样你就没有异常处理程序代码的多个副本。

我建议在 http://connect.microsoft.com/ 提交功能请求(或查看其他人是否已经请求,并添加您的投票。)

【讨论】:

    【解决方案2】:

    这是一个“干净”的解决方法,它将异常放入 TestBase.TestContext 属性(或您希望在 TestBase 实例中的任何位置)。

    该示例使用postsharp(这是一个 AOP 库)在编译时将 try-catch 注入您的代码。它将注入所有具有 [TestMethod] 属性的方法。 - postsharp 免费版可以完成这项工作,无需许可证。

    您要做的第一件事是创建 AOP 属性。属性定义了在异常情况下将执行的操作,并且 + 定义了注入的条件,这就是您的操作方式:

    /// <summary>
    /// Catch exceptions of tests and save them in <see cref="TestBase"/> under TestContext.Properties. This is done since MSTEST does not supply any mechanism to catch tests exceptions.
    /// </summary>
    [SerializableAttribute]
    public class CodedTestsExceptionsHandlingAop : OnExceptionAspect
    {
        /// <summary>
        /// The name of the property that will be added to the test context properties object.
        /// </summary>
        public const string FailureExceptionProerty = "FailureException";
    
        /// <summary>
        /// Save the exception in a <see cref="TestBase"/> and rethrow.
        /// </summary>
        /// <param name="args"></param>
        public override void OnException(MethodExecutionArgs args)
        {
            var testBase = (Framework.TestBase) args.Instance;//The instance running the test inherits from TestBase.
            testBase.TestContext.Properties.Add("FailureException", args.Exception);
    
            args.FlowBehavior = FlowBehavior.RethrowException;
        }
    
        /// <summary>
        /// Make sure only test methods will get this AOP.
        /// </summary>
        /// <param name="method"></param>
        /// <returns></returns>
        public override bool CompileTimeValidate(MethodBase method)
        {
            if (method.IsDefined(typeof(TestMethodAttribute)))
                return true;
    
            return false;
        }
    }
    

    第二件事,您必须将以下程序集级别属性添加到您的测试项目(如果它与您的 TestBase 不在同一个项目中,还需要安装 postsharp),这将应用 AOP 注入测试程序集:

    [assembly: CodedTestsExceptionsHandlingAop(AttributeTargetTypes = "*", AttributeTargetElements = MulticastTargets.Method)]
    

    【讨论】:

      【解决方案3】:

      如果您只是想测试预期的异常,可以使用ExpectedExceptionAttribute

      我认为,当单元测试是意外异常并且您想要记录或收集有关异常的额外信息时,能够获取单元测试的异常会更有用,而不是依靠 TestExplorer 来查找检查失败测试。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-07
        • 1970-01-01
        • 2019-03-22
        相关资源
        最近更新 更多