C# 努尼特:为什么';t断言抛出<;T>;抓住我的例外?
尊敬的约翰·斯基特先生建议我设计一个简单的测试程序,分离并证明我遇到的问题,并重新提出这个问题。我是应尊敬的约翰·斯基特先生的要求重新发布这个问题的。这个问题源于,所以如果听起来很熟悉,请原谅我。你可以从这个问题中收集更多关于这个问题的细节 我遇到的问题涉及NUnit 2.5.9中的C# 努尼特:为什么';t断言抛出<;T>;抓住我的例外?,c#,.net,exception,nunit,C#,.net,Exception,Nunit,尊敬的约翰·斯基特先生建议我设计一个简单的测试程序,分离并证明我遇到的问题,并重新提出这个问题。我是应尊敬的约翰·斯基特先生的要求重新发布这个问题的。这个问题源于,所以如果听起来很熟悉,请原谅我。你可以从这个问题中收集更多关于这个问题的细节 我遇到的问题涉及NUnit 2.5.9中的Assert.Throws。有时,它将无法捕获TestDelegate调用的方法中抛出的任何异常。我在下面的代码中以可复制的方式固定了这种行为。(当然,这可能是我的机器出现故障的情况™. 为了重现错误,我创建了一个包
Assert.Throws
。有时,它将无法捕获TestDelegate调用的方法中抛出的任何异常。我在下面的代码中以可复制的方式固定了这种行为。(当然,这可能是我的机器出现故障的情况™.
为了重现错误,我创建了一个包含两个C#DLL项目的解决方案:
- 第一个包含一个类,带有一个公共方法。该方法是一个扩展方法,它封装了创建
、填充其参数并在其上调用SqlCommand
所需的逻辑。此项目不包括其他引用ExecuteScalar
- 第二个包含一个类和两个方法,用于测试第一个DLL中的方法是否按预期工作。此项目引用第一个DLL,并包含对NUnit框架的引用。未引用其他程序集
Assert.Throws
正确调用ExecuteScalar
扩展方法ExecuteScalar
测试其参数的空值抛出新ArgumentNullException(…)
的行throw
后,应用程序的控制不会立即转移到Assert.Throws
。相反,它会在ExecuteScalar
中的下一行继续namespace NUnit_Anomaly
{
using System;
using System.Data;
using System.Data.SqlClient;
public static class Class1
{
public static T ExecuteScalar<T>(this SqlConnection connection, string sql)
{
if (connection == null)
{
throw new ArgumentNullException("connection");
}
if (sql == null)
{
throw new ArgumentNullException("sql");
}
using (var command = connection.CreateCommand())
{
command.CommandType = CommandType.Text;
command.CommandText = sql;
return (T)command.ExecuteScalar();
}
}
}
}
namespace NUnit\u异常
{
使用制度;
使用系统数据;
使用System.Data.SqlClient;
公共静态类1
{
公共静态T ExecuteScalar(此SqlConnection连接,字符串sql)
{
if(连接==null)
{
抛出新的ArgumentNullException(“连接”);
}
if(sql==null)
{
抛出新的ArgumentNullException(“sql”);
}
使用(var command=connection.CreateCommand())
{
command.CommandType=CommandType.Text;
command.CommandText=sql;
return(T)command.ExecuteScalar();
}
}
}
}
测试用例
namespace NUnit_Tests
{
using System;
using System.Data.SqlClient;
using System.Diagnostics;
using NUnit.Framework;
using NUnit_Anomaly;
[TestFixture]
public class NUnitAnomalyTest
{
[Test]
public void ExecuteDataSetThrowsForNullConnection()
{
Assert.Throws<ArgumentNullException>(() => ((SqlConnection)null).ExecuteScalar<int>(null));
}
[Test]
public void ExecuteDataSetThrowsForNullSql()
{
const string server = "MY-LOCAL-SQL-SERVER";
const string instance = "staging";
string connectionString = String.Format("Data Source={0};Initial Catalog={1};Integrated Security=True;",
server,
instance);
using (var connection = new SqlConnection(connectionString))
{
Assert.Throws<ArgumentNullException>(() => connection.ExecuteScalar<int>(null));
}
}
}
}
名称空间NUnit\u测试
{
使用制度;
使用System.Data.SqlClient;
使用系统诊断;
使用NUnit.Framework;
利用NUnit_异常;
[测试夹具]
公共类NunitomalyTest
{
[测试]
public void ExecuteDataSetThrowsForNullConnection()执行
{
抛出(()=>((SqlConnection)null.ExecuteScalar(null));
}
[测试]
public void ExecuteDataSetThrowsForNullSql()
{
const string server=“MY-LOCAL-SQL-server”;
const string instance=“staging”;
string connectionString=string.Format(“数据源={0};初始目录={1};集成安全性=True;”,
服务器,
实例);
使用(var连接=新的SqlConnection(connectionString))
{
Assert.Throws(()=>connection.ExecuteScalar(null));
}
}
}
}
最终的结果是测试在不应该的情况下失败。据我所知,Assert.Throws
应该捕获我的异常,测试应该通过
更新
我接受了Hans的建议并检查了异常对话框。我没有破坏抛出的异常,而是破坏了未处理的用户异常。显然,这就是为什么在抛出异常时调试器会闯入IDE。清除复选框修复了问题,并且Assert.Throws
拾取了它。但是,如果我没有这样做,则s、 我不能只按F5继续执行,否则异常将变成NullReferenceException
所以现在的问题是:我可以在每个项目的基础上配置异常中断吗?我只想在测试时这样做,而不是一般情况下这样做。实际发生的情况是
断言。抛出是否捕获您的异常,但是Visual Studio会在第一次出现异常时停止。您可以通过唱F5;Visual Studio将愉快地继续执行
作为例外助手告诉您,异常是未处理的<强> >用户代码< /强>。因此我们知道VisualStudio出于某种原因不认为NUnbe是用户代码。
如果您知道在哪里查找,Visual Studio实际上会以纯文本形式告诉您:
堆栈跟踪中也有这一事实的证据:
解决方案1:使用带有调试符号的NUnit调试版本。这样,就不会将异常视为“未经用户代码处理”。这不是小事,但从长远来看可能会更好
解决方案2:关闭Visual Studio调试设置中的“仅启用我的代码”复选框:
另外,我没有考虑避免使用Assert.Thr的变通方法