繁体   English   中英

NUnit,Assert.Throws或[ExpectedException]都不引发抛出异常

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM