例外资产与负债;在VS中调试C#项目

例外资产与负债;在VS中调试C#项目,c#,visual-studio,exception,assert,nunit-2.5,C#,Visual Studio,Exception,Assert,Nunit 2.5,我们使用NUnit和VisualStudio编写C#.NET代码已有一段时间了。测试异常是以 旧语法: 现在NUnit发布了2.5.2版,它引入了Assert.Throws(类型expectedExceptionType,TestDelegate代码)这使得异常测试更加灵活。我们的异常测试现在如下所示: 新语法: [测试] public void TestWithNullBufferArgument() { ArgumentNullException ex=Assert.Throws(()=>_

我们使用NUnit和VisualStudio编写C#.NET代码已有一段时间了。测试异常是以

旧语法:

现在NUnit发布了2.5.2版,它引入了
Assert.Throws(类型expectedExceptionType,TestDelegate代码)这使得异常测试更加灵活。我们的异常测试现在如下所示:

新语法:

[测试]
public void TestWithNullBufferArgument()
{
ArgumentNullException ex=Assert.Throws(()=>_testInstance.TestFunction(null));
//现在您可以检查异常及其属性
AreEqual(例如,Message,“参数为空”);
}
我们的问题是,如果使用Assert.Throws,当使用NUnit(控制台或GUI运行程序)调试程序时,Visual Studio将弹出一个显示未处理异常的窗口

为了澄清这一点:我们将包含单元测试的VS项目设置为在调试时运行nunit-x86.exe。(请参见“项目属性”、“调试”选项卡,“启动操作”设置为运行nunit-x86.exe)

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

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


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

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

我认为您被NUnit断言蒙蔽了双眼。您可以通过简单的尝试/捕获来实现同样的目标

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

现在,你需要的东西都有了。如果没有引发异常,并且您的常规代码可以按预期处理异常,则您将失败。

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

“启用此功能时,调试器仅显示并单步执行用户代码(“我的代码”),忽略系统代码和其他已优化或没有调试符号的代码”(请参阅“”)

通常,您的nunit.framework.dll发行版本没有相应的nunit.framework.pdb文件

因此有两种选择:

  • 禁用“仅我的代码”功能

  • 下载nunit的源代码(从),在调试模式下构建它们,将所有nunit.framework.*(dll、pdb、xml)放入解决方案中的lib或其他目录中,并在测试项目中引用该nunit.framework.dll


  • 希望这有帮助。

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

    如果在编译库(在本例中为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方法中提取了一个片段)测试了我自己的手卷库。我想这是VS的一个特性或“特性”

    它让我们没有那么多选择:

  • 如前所述,筛选异常

  • 重新编译nunit.framework.dll供本地使用,以避免这些恼人的停止

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

    编辑:

    找到了另一个选项

  • 在我的例子中,取消选中“在模块加载时抑制JIT优化”也可以做到这一点,即使编译的库没有调试信息。但是,它仅在项目以版本配置运行时才起作用
    这是可行的,但也意味着如果调试实际程序而不是单元测试,则不会捕获任何异常。理想情况下,我们应该寻找一种方法,在调试单元测试时如何避免它。感谢您的提示,如果没有其他问题,这可能是一个可接受的解决方案。如果您编写两个单元测试呢?一个确保抛出异常,第二个将执行?我也这么想。不幸的是,由于委托和断言中的代码引发了异常,因此它不起作用。Throws期望引发异常。您显示的测试示例不符合您显示的语法。另外,“当NUnit…用于调试程序时”是什么意思?你是说你只是在运行测试,还是在调试器中运行测试(我知道TestDriven.NET可以做到这一点;不知道NUnit运行程序)?嗨,杰!很抱歉给你带来了困惑。显示了两种不同类型的语法:new和old。我们已经从旧语法切换到新语法,现在使用Assert.Throws约束。我们正在调试程序中运行测试,到目前为止,它运行得很好,很容易看出哪里出了问题,因为VS将直接跳到导致异常的点。使用新语法,我们将所有异常测试作为“误报”,而使用旧语法,只有真正的异常才会中断执行。您是对的,这将是在单元测试中处理异常的基本方法。NUnit异常断言的美妙之处在于,您可以测试抛出的异常的某些属性。例如,您可以测试传递给异常的参数是否正确。我喜欢并使用它,我想保留它。难道你不能用这种方式测试异常的参数吗?而不是catch{}你可以说catch(Exception ex){Assert.IsTrue(ex.Whatever);}是的,这确实是真的。又好又简单,我真的很喜欢!我原来的问题是
    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(); }, "");    
    }