【问题标题】:ExceptionAsserts & debugging your C# project in VSExceptionAsserts & 在 VS 中调试你的 C# 项目
【发布时间】:2010-01-18 15:28:14
【问题描述】:

一段时间以来,我们一直在使用 NUnit 和 VisualStudio 编写 C# .NET 代码。测试异常是以

的风格完成的

旧语法:

[Test]
[ExpectException(typeof(ExceptionType))] 
public void TestExceptionType()
{

}

现在 NUnit 发布了 2.5.2 版本,其中引入了 Assert.Throws( Type expectedExceptionType, TestDelegate code ); 这使得异常测试更加灵活。我们的异常测试现在看起来像这样:

新语法:

[Test]
public void TestWithNullBufferArgument()
{
   ArgumentNullException ex = Assert.Throws<ArgumentNullException>(() => _testInstance.TestFunction(null));

   // now you can examine the exception and it's properties
   Assert.AreEqual(ex.Message, "Argument was null");
}

我们的问题是,如果使用 Assert.Throws,当使用 NUnit(控制台或 GUI 运行程序)调试程序时,Visual Studio 会弹出一个显示未处理异常的窗口。

澄清这一点:我们已将包含单元测试的 VS 项目设置为在调试时运行 nunit-x86.exe。 (查看项目属性,调试选项卡,启动动作设置为运行nunit-x86.exe)

这会阻止 NUnit 继续测试。按 F5 可以继续调试/单元测试,但这不是一个可行的解决方案。

有什么办法可以避免这种情况吗?在 Assert.Throws 周围放置一个 try...catch 块没有任何作用,因为异常发生在委托代码中。

我希望有人能对此有所了解。

【问题讨论】:

  • 您展示的测试示例不符合您展示的语法。另外,“当使用 NUnit ... 调试程序时”是什么意思?你的意思是你只是在运行测试,还是在调试器中运行测试(我知道 TestDriven.NET 可以做到这一点;不知道 NUnit 运行器)?
  • 嗨,杰!对困惑感到抱歉。显示了两种不同类型的语法:新的和旧的。我们已经从旧语法切换到新语法,现在使用 Assert.Throws 约束。我们正在调试器中运行测试,到目前为止它运行良好,并且很容易看出出了什么问题,因为 VS 会直接跳转到导致异常的地方。使用新语法,我们将所有异常测试都视为“误报”,而使用旧语法,只有真正的异常会中断执行。

标签: c# visual-studio exception assert nunit-2.5


【解决方案1】:

问题本身出现的原因很可能是您启用了仅启用我的代码选项(工具->选项->调试->常规->启用仅我的代码)。

“启用此功能后,调试器仅显示并进入用户代码(“我的代码”),忽略系统代码和其他已优化或没有调试符号的代码”(参见“General, Debugging, Options Dialog Box”)

通常你有一个 nunit.framework.dll 的发布版本,它没有相应的 nunit.framework.pdb 文件。

所以有两种选择:

  1. 禁用“仅我的代码”功能

  2. 下载 nunit 的源代码(来自http://www.nunit.org/index.php?p=download),在调试模式下构建它们,将所有 nunit.framework.*(dll、pdb、xml)放入解决方案中的 lib 或其他目录并引用该 nunit。 framework.dll 在您的测试项目中。

希望这会有所帮助。

【讨论】:

  • dh,这是一个有趣的思路。我尝试了选项 1(只是因为它很快而且我没有时间尝试数字 2),不幸的是它对我没有任何影响。如果我现在有更多未处理的异常。 Assert.Throws 导致未处理异常的问题仍然存在。
  • 我不知道。这听起来像我的设置,只是我调用的是 nunit-gui.exe
  • 我已经为 nunit-gui 尝试过,结果与 nunit-console 相同。仍然有提供调试符号的选项,希望对您有用。
  • 查看后:“只是我的代码”如果禁用该选项,VS 将不会停止任何异常。这也不是我想要的。我想要旧的 [ExpectException] 语法的行为,它不会在预期的异常上停止,但会在预期的异常上停止。
  • @dh,我已经尝试过选项 2 并且有效。感谢上帝!这有点 hack,但我愿意使用它,直到它与 NUnit 的 Release 版本一起正常工作。
【解决方案2】:

同样的问题也困扰了我一段时间,我做了一些测试,发现如下:

如果一个库(在本例中为 nunit)编译时将调试信息设置为“无”,那么如果使用该库执行类似于下面的构造并且委托的代码抛出异常,则 VS 停止抱怨未处理的异常通过用户代码。

库代码:

public static Exception Throws(TestDelegate code, string message)
{
    Exception caughtException = null;

    try
    {
        code();
    }
    catch (Exception ex)
    {
        caughtException = ex;
    }        

    return caughtException;
}

客户端代码:

private void btnTest_Click(object sender, EventArgs e)
{
  var ex = MyAssert.Throws(() => { throw new Exception(); }, "");    
}

将库项目的调试信息设置为“none”以外的任何其他选项都可以解决问题,即调试器不再停止那些有点“未处理”的异常。我用上面的代码用 nunit 和我自己的手动库测试了它(从 nunit 的 Throws 方法中获取了一个 sn-p)。我想这是VS的一个特性或“特性”。

这让我们没有太多选择:

  1. 如前所述过滤异常

  2. 重新编译 nunit.framework.dll 以供本地使用,以避免那些烦人的停止

其他选择可能是联系 MS 或 NUnit 团队或两者,并要求他们调查/澄清问题并以最低级别的调试信息分别编译 NUnit。

编辑:

又找到了一个选项。

  1. 在我的情况下,取消选中“在模块加载时抑制 JIT 优化”也可以解决问题,即使编译时没有调试信息的库也是如此。但是,它仅在项目在发布配置中运行时才有效。

【讨论】:

  • dyadenka,非常感谢您的详细反馈!不幸的是,dh 不久前提出了相同的建议(在调试配置中重新编译 nunit 框架),所以他得到了赏金。我已经就这个问题写信给 nunit 邮件列表,如果他们想出更好的解决方案,我们会这样做。
  • 别担心,赏金不是目标,主要目标是解决 VS 中那些烦人的停止问题。
【解决方案3】:

我认为你被 NUnit 断言蒙蔽了双眼。您可以通过简单的 try/catch 实现相同的目标。

try
{
  _testInstance.TestFunction(null);
  Assert.Fail("The method should have thrown...");
}catch{}

现在,您拥有所需的一切。如果没有抛出异常并且您的常规代码可以按预期处理异常,那么您将失败。

【讨论】:

  • 你是对的,这将是单元测试中处理异常的基本方法。 NUnit 异常断言的美妙之处在于您可以测试抛出的异常的某些属性。例如,您可以测试传递给异常的参数是否正确。我喜欢并使用它,我想保留它。
  • 你不能用这种方式测试异常的参数吗?而不是 catch{} 你可以说 catch(Exception ex) { Assert.IsTrue(ex.Whatever); }
  • 是的,确实如此。好看又简单,我喜欢!我最初的问题是关于 Assert.Throws 方法引起的问题,因此我将赏金给了解决当前问题的人。
【解决方案4】:

是否可以通过禁用异常来实现。 打开 Debug/Exceptions 菜单,然后搜索您的 Exception。

【讨论】:

  • 这可行,但这也意味着如果调试真实程序而不是单元测试,则不会捕获任何异常。理想情况下,我们会寻找一种在调试单元测试时避免它的方法。感谢您的提示,如果没有其他问题,这可能是一个可以接受的解决方案。
  • 如果你写两个单元测试呢?一个确保抛出异常,第二个将执行?
  • 我也考虑过。不幸的是,它不起作用,因为异常是由委托中的代码引发的,并且 Assert.Throws 预计会引发异常。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多