![](/img/trans.png)
[英]NUnit: Why Doesn't Assert.Throws<T> Catch My ArgumentNullException?
[英]NUnit, Neither Assert.Throws nor [ExpectedException] Catch Thrown Exception
在开始之前,我想说明一下,我已经检查了这个问题和这个问题的解决方案。
测试方法
public static DataSet ExecuteDataSet(this SqlConnection connection, string sql)
{
if (null == connection || null == sql)
{
throw new ArgumentNullException();
}
using (var command = connection.CreateCommand())
{
// Code elided for brevity
}
}
测试方法
[Test]
[ExpectedException(typeof(ArgumentNullException))]
public void ExecuteDataSetThrowsForNullConnection()
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
[Test]
public void ExecuteDataSetThrowsForNullSql()
{
Assert.Throws<ArgumentNullException>(
() => Resource.Connection.ExecuteDataSet(null)
);
}
奇怪的行为
测试方法的两个版本均未捕获进入ExecuteDataSet
方法后立即引发的ArgumentNullException
。 控制流前进到下一行( using (var command = connection.CreateCommand())
),而发生了NullReferenceException
(当然,这两个测试用例都不会对其进行处理,因为它永远都不会抛出 )。
最初,第一个测试方法( ExecuteDataSetThrowsForNullConnection
)看起来就像第二个测试方法( ExecuteDataSetThrowsForNullSql
)。 当Assert.Throws
无法捕获该异常时,我进行了一些研究,并指出一些人建议改用ExpectedException
。 我相应地修改了测试代码,但无济于事。
作为记录,这是在NUnit 2.5.9下测试的32位.NET 3.5代码。 我正在使用TestDriven.NET进行Visual Studio集成,并安装了最新版本的NCover和NDepend。
TL; DR问题
为什么测试方法没有捕获到抛出的异常,我该如何解决?
编辑
此版本的测试方法有效。
[Test]
public void ExecuteDataSetThrowsForNullConnection()
{
try
{
((SqlConnection)null).ExecuteDataSet("SELECT TOP 1 * FROM prep");
}
catch(ArgumentNullException e)
{
Assert.AreEqual(true, true);
}
catch (Exception e)
{
Assert.Fail("Expected ArgumentNullException, but {1} was thrown instead.", e.GetType().Name);
}
}
我的猜测是您并未真正测试您认为的代码。 尝试放入一些Console.WriteLine
语句,看看它们是否已打印。 如果在throw
语句上放置一个断点并在调试器中运行测试,该断点会命中吗? 如果将控制权传递给下一条语句,则意味着永远不会引发异常-除非您发现了一个非常奇怪的CLR错误,否则无法以允许在执行throwing方法中继续执行的方式捕获该异常。
我已经写了很多这样的代码,并且在NUnit中从未失败过。
顺便说一句,我认为在ArgumentExceptions中包含参数名称是一种很好的做法,所以我会写:
if (connection == null)
{
throw new ArgumentNullException("connection");
}
if (sql == null)
{
throw new ArgumentNullException("sql");
}
不幸的是,这个问题很冗长,并且在代码中以字符串形式重复了参数名称...但是这样做很容易就可以正确使用(尤其是在ReSharper帮助验证名称的情况下),并且如果这在生产中触发的话,它可能会非常有用。 。 (有一些怪异的技巧可以通过其他方式验证参数,但我怀疑您不想看到这些...)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.