有没有办法可以使用TestContext或基础测试类上的其他方法来处理由MSTest框架处理的异常?
如果在我的一个测试中发生未处理的异常,我想旋转exception.Data字典中的所有项目并将它们显示给测试结果,以帮助我找出测试失败的原因(我们通常会添加数据到异常以帮助我们在生产环境中调试,所以我想做同样的测试)。
注意:我没有测试异常是支持HAPPEN(我还有其他测试),我正在测试一个有效的案例,我只需要查看异常数据。
这是我正在谈论的代码示例。
[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;
}
}
答案 0 :(得分:3)
我一直遇到同样的问题,似乎没有对此表示支持。你甚至无法使用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/提交功能请求(或查看其他人是否已请求此功能,并添加您的投票。)
答案 1 :(得分:1)
这是一个“干净”的工作,它将把异常放入TestBase.TestContext属性(或者你想在TestBase实例中的任何地方)。
该示例使用postsharp(这是一个AOP库)在编译时为您的代码注入try-catch。它将注入具有[TestMethod]属性的所有方法。 - postsharp免费版将完成工作,无需通过许可证。
您要做的第一件事是创建AOP属性。这些属性定义了在异常和+ define注入条件下将要完成的操作,这是你如何做的:
/// <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)]
答案 2 :(得分:0)
如果您只是想测试预期的例外情况,可以使用ExpectedExceptionAttribute
我认为能够获得单元测试的异常会在出现意外异常时更有用,并且您希望记录或收集有关异常的额外信息,而不是依靠TestExplorer来查找检查失败测试