MSTest测试上下文异常处理
有没有办法让我可以使用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;
}
}
我一直在遇到同样的问题,似乎没有支持。 你甚至不能使用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/上提交此功能请求(或者查看是否有其他人已经请求了它并添加您的投票。)
这里是一个“干净的”工作,将把异常放到TestBase.TestContext属性中(或者你想在你的TestBase实例中的任何地方)。
该示例使用postsharp(这是一个AOP库)在编译时向您的代码注入try-catch。 它将注入所有具有[TestMethod]属性的方法。 - postharp免费版将完成这项工作,无需通过许可证。
你必须做的第一件事是创建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的同一个项目中,它也需要安装postharp),这将在测试组件中应用AOP注入:
[assembly: CodedTestsExceptionsHandlingAop(AttributeTargetTypes = "*", AttributeTargetElements = MulticastTargets.Method)]
如果你只是想测试预期的异常,你可以使用ExpectedExceptionAttribute
我认为能够获得单元测试的异常会更有用,因为它是一个意外的异常,并且您想记录或收集有关该异常的额外信息,而不是依靠TestExplorer来查找检查失败的测试。
链接地址: http://www.djcxy.com/p/44149.html上一篇: MSTest Test Context Exception Handling
下一篇: Guidelines for a Password Strength Meter (Password checker) Design