【问题标题】:Debugging unit tests that fail due to a StackOverflow exception调试由于 StackOverflow 异常而失败的单元测试
【发布时间】:2013-02-26 13:31:40
【问题描述】:

每当单元测试由于StackOverflowException 而失败时,单元测试进程会立即退出 - 找出发生了什么(我知道)的唯一方法是调试通过以下获得的单元测试进程的崩溃转储此处找到的步骤

获取在抛出StackOverflowException 时正在运行的单元测试的名称的最简单方法是什么?即使在调试单元测试时,我也很难找到当前单元测试的名称,因为它位于堆栈的底部,并且 Visual Studio 不会在调试窗口中显示整个堆栈,因为它太大了。

有没有什么方法可以在不收集和调试故障转储的情况下找出哪个单元测试失败?

【问题讨论】:

  • 我不确定是什么截断了异常。您可以尝试在监视和/或中间窗口中使用new System.Diagnostics.StackTrace(true) 创建自己的堆栈跟踪吗?也许这将为您提供完整的跟踪。
  • @Caramiriel 运行时,交互式调试会提供Cannot evaluate expression because the current thread is in a stack overflow state.,但在调试故障转储时,您无法运行即时表达式,因为此时进程实际上并未运行。没有显示整个堆栈跟踪,因为它很大。
  • @Justin:如果您的 Visual Studio 架构(例如 x86)与您的应用程序相匹配,那么您还可以通过在即时窗口中键入 !clrstack 来加载 SOS 并转储堆栈跟踪。似乎为我工作。 (0028ed6c 00340147 ConsoleApplication45.Program.Rec() 0028edac 003400fb ConsoleApplication45.Program.Main(System.String[]))
  • 您的单元测试流程/线束/工具是什么?您应该获得进度日志(可能是控制台输出?),因此即使工具无法正常处理StackOverflowException,您也应该能够在日志中看到正在运行的测试方法的名称最后。

标签: c# .net unit-testing stack-overflow


【解决方案1】:

正如this other question 中所述,除非您自己抛出异常,否则您无法真正捕获堆栈溢出异常。

因此,作为解决问题的方法(不是真正的解决方案),您可以在代码中插入方法调用以检测堆栈溢出,然后手动抛出异常并稍后捕获。

[TestClass]
public class TestStackOverflowDetection
{
    [TestMethod]
    public void TestDetectStackOverflow()
    {
        try
        {
            InfiniteRecursion();
        }
        catch (StackOverflowException e)
        {
            Debug.WriteLine(e);
        }
    }

    private static int InfiniteRecursion(int i = 0)
    {
        // Insert the following call in all methods that
        // we suspect could be part of an infinite recursion 
        CheckForStackOverflow(); 

        // Force an infinite recursion
        var j = InfiniteRecursion(i) + 1;
        return j;
    }

    private static void CheckForStackOverflow()
    {
        var stack = new System.Diagnostics.StackTrace(true);
        if (stack.FrameCount > 1000) // Set stack limit to 1,000 calls
        {
            // Output last 10 frames in the stack
            foreach (var f in stack.GetFrames().Reverse().Take(30).Reverse())
                Debug.Write("\tat " + f);

            // Throw a stack overflow exception
            throw new StackOverflowException();
        }
    }

【讨论】:

    【解决方案2】:

    看看RuntimeHelpers.EnsureSufficientExecutionStack 方法(http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.runtimehelpers.ensuresufficientexecutionstack.aspx)。您可能希望在递归方法中调用它以提前获取 InsufficientExecutionStackException。

    【讨论】:

      猜你喜欢
      • 2014-04-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-22
      • 1970-01-01
      • 2013-08-12
      • 1970-01-01
      • 2012-04-10
      相关资源
      最近更新 更多