2013-03-11 17 views
14

Zawsze, gdy test jednostkowy nie powiedzie się z powodu StackOverflowException, proces testu jednostkowego natychmiast się kończy - jedynym sposobem, aby dowiedzieć się, co się stało (o czym mi wiadomo) jest debugowanie zrzutu awaryjnego procesu testów jednostkowych uzyskanych przez następujące znaleźć tutajTesty jednostek debugowania, które zawiodły z powodu wyjątku StackOverflow

Jaki jest najprostszy sposób na uzyskanie nazwę badanej jednostki, który był uruchomiony w momencie, że StackOverflowException został rzucony kroki? Nawet podczas debugowania testu urządzenia staram się znaleźć nazwę bieżącego testu jednostki, który znajduje się na dole stosu, a Visual Studio nie wyświetli całego stosu w oknie debugowania, ponieważ jest zbyt duży.

Czy jest jakiś sposób sprawdzenia, który test jednostkowy nie powiódł się, nie zbierając i nie debugując zrzutów awaryjnych?

+0

Nie jestem pewien, co jest obcięcie wyjątku. Czy mógłbyś spróbować zrobić własny stacktrace za pomocą 'new System.Diagnostics.StackTrace (true)' w zegarku i/lub oknie pośrednim? Może to zapewni ci pełny ślad. – Caramiriel

+1

@Caramiriel Uruchamianie tego podczas interaktywnego debugowania daje komunikat "Nie można ocenić wyrażenia, ponieważ bieżący wątek znajduje się w stanie przepełnienia stosu.", Nie można uruchamiać bezpośrednich wyrażeń podczas debugowania zrzutu awaryjnego, ponieważ proces w tym momencie nie działa. Cały ślad stosu nie jest pokazany, ponieważ jest masywny. – Justin

+0

@Justin: Jeśli twoja architektura studia wizualnego (np. X86) pasuje do twojej aplikacji, możesz również załadować SOS i zrzucić stos, wpisując '! Clrstack' w bezpośrednim oknie. Wydaje się, że pracujesz dla mnie. ('0028ed6c 00340147 ConsoleApplication45.Program.Rec() 0028edac 003400fb ConsoleApplication45.Program.Main (System.String [])') – Caramiriel

Odpowiedz

1

Jak wspomniano w artykule this other question, nie można naprawdę złapać wyjątku przepełnienia stosu, chyba że sam go wyrzucisz.

Tak więc, jako obejście problemu (w rzeczywistości nie jest to rozwiązanie), można wstawić kod wywołania metody w celu wykrycia przepełnienia stosu, a następnie ręcznie wyrzucić wyjątek i przechwycić go później.

[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(); 
     } 
    } 
Powiązane problemy