确定导致异常的原因的正确方法是什么,纠正它?
请考虑以下代码。我尝试解析一串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;
}
}
这感觉就像一个黑客。这样做的正确方法是什么?
答案 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
}
您可以使用多个字段来识别异常类型,例如InnerException
,StackTrace
和Data
。正如@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框架的一部分提供的。