如何测试抛出异常的具体原因?

时间:2018-01-20 16:59:03

标签: c# xml xmldocument

确定导致异常的原因的正确方法是什么,纠正它?

请考虑以下代码。我尝试解析一串XML,但偶尔,传入的XML不会是顶级的,这意味着它需要被根元素包围。

发生这种情况时,解析器抛出一个XmlException,但由于很多原因它可能会抛出它。我想抓住这个具体原因

我这样做,我承认可能不是很好:

var doc = new XmlDocument();
try
{
    doc.LoadXml(xml);
}
catch(XmlException e)
{
    if(e.Message.Contains("multiple root elements"))
    {
        doc.LoadXml($"<root>{xml}</root>");
    }
    else
    {
        throw e;
    }
}

这感觉就像一个黑客。这样做的正确方法是什么?

3 个答案:

答案 0 :(得分:2)

您可以按照此处的说明尝试切换XmlException.HResult

https://msdn.microsoft.com/en-us/library/system.xml.xmlexception(v=vs.110).aspx

我唯一不确定的是,它是否指向特定的异常类型(如XmlException)或特定的异常“message”。

如果这没有帮助,我认为除了检查消息之外别无选择。

编辑:另外,如上所述,您应该throw;而不是throw e;,因为第二个会清除StackTrace。 ReSharper也警告过这个。

答案 1 :(得分:2)

C#的一项新功能允许您使用catch关键字过滤when子句中的例外:

try
{

} 
catch (XmlException ex) when ( ex.Message.Contains(...) )
{
   //handle
}

您可以使用多个字段来识别异常类型,例如InnerExceptionStackTraceData。正如@DavidHruška建议的那样,HResult属性也是检查识别异常类型的好地方

Message不是用于检查的最佳属性,因为它通常针对内置类型进行本地化,因此可能与其他文化设置看起来不同。

答案 2 :(得分:1)

有多种方法可以实现您尝试做的事情。 不同的测试框架也带来了自己的工具来帮助解决这个问题。 例如,如果您正在使用MSVS Test Framework,最简单的选择是仅检查异常类型。在这种情况下,您只需使用&#34; ExceptedExceptionAttribute&#34;标记测试方法。并指定从方法中抛出的预期异常类型,如下所示:

[TestMethod]
[ExpectedException(typeof(ArgumentException))]
public void Action_ThrowsException()
{
    // test logic here
}

还有另一个可用的构造函数,它允许将确切的异常消息指定为第二个参数,这很少使用。您可以在MSDN中找到ExpectedExceptionAttribute的文档。

另一个选项,你有更多的控制权,将是其他答案中已经建议的,可以封装在辅助方法中,如下所示:

private static T Throws<T>(Action action) where T : Exception
{
    try
    {
        action();
        Assert.Fail();
    }
    catch (T ex)
    {
        // This exception was expected.
        return ex;
    }
}

使用此辅助方法,您现在可以使用以下测试方法:

[TestMethod]
public void Action_ThrowsException()
{
    // test logic here
    ArgumentException aex = Throws<ArgumentException>(()=>{
        // Test logic here
    });

    Assert.AreEqual("Expected error message", aex.Message);
}

如您所见,此选项为您提供了更高的灵活性,因为您现在可以明确验证异常的其他方面。

仅供参考:第二个解决方案是作为xUnit框架的一部分提供的。