Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get 100% code coverage for "catch with rethrow" block in VB.NET in Visual Studio 2010 Ultimate?

I am unable to achieve 100% code coverage for a "catch with rethrow" block in my VB.NET source code. My workplace IDE is Visual Studio 2010 Ultimate. Below example represents a simplified version of my actual problem.

Source in C#: (light-blue background indicates full code coverage)

Source in C#


Equivalent source in VB.NET: (yellow background indicates partial code coverage)

Source in VB.NET


MSTests for both C# and VB.NET source (intended to achieve 100% code coverage)

MSTests


Code Coverage Report

Code Coverage Report


The code coverage report shows 100% for C#, but only 91.67% for VB.NET. It also shows 1 block of code with 0 lines being uncovered in VB.NET.

Is this an issue with the tool? Or am I missing something obvious?

EDIT #1: Sharing source code as requested by @Raptor

Source code in C#

public class CodeCoverage
{
   public void DoWork(bool flag = false)
   {
      try
      {
         Thread.Sleep(1);

        if (flag)
            {
               throw new Exception("test");
            }
      }
      catch (Exception ex)
      {
         throw new Exception(string.Format("something happened: {0}", ex.Message));
      }
   }
}


Source code in VB.NET

Public Class CodeCoverage2
   Public Sub DoWork(Optional ByVal flag As Boolean = False)
      Try
            Thread.Sleep(1)

            If flag Then
                Throw New Exception("test")
            End If
        Catch ex As Exception
            Throw New Exception(String.Format("something happened: {0}", ex.Message))
        End Try
    End Sub
End Class


Source code for MSTests

[TestClass]
public class CodeCoverageTest
{
   [TestMethod]
   public void DoWorkTest()
   {
      var obj = new CodeCoverage();
      obj.DoWork();
   }

   [TestMethod]
   [ExpectedException(typeof(Exception))]
   public void DoWorkTest2()
   {
      var obj = new CodeCoverage();
      obj.DoWork(true);
   }

   [TestMethod]
   public void DoWorkTest3()
   {
      var obj = new CodeCoverage2();
      obj.DoWork();
   }

   [TestMethod]
   [ExpectedException(typeof(Exception))]
   public void DoWorkTest4()
   {
      var obj = new CodeCoverage2();
      obj.DoWork(true);
   }
}
like image 906
Channs Avatar asked Jan 05 '15 05:01

Channs


2 Answers

If you look at the IL generated for the VB project in debug mode, you will see the following in the catch block:

IL_002f: call string [mscorlib]System.String::Format(string, object)
IL_0034: newobj instance void [mscorlib]System.Exception::.ctor(string)
IL_0039: throw

IL_003a: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
IL_003f: leave.s IL_0041

Since IL_0039 throws, you would never hit IL_003a, so you have code that never gets executed.

In release mode, the IL for ClearProjectError is not generated.

like image 142
John Koerner Avatar answered Oct 18 '22 04:10

John Koerner


Not enough reputation to comment on John Koerner's reply, which is correct, but to add - we solved this by having our test target run in release mode. This causes code coverage to work properly.

EG:

DEBUG Configuration:  
MyApplication - RELEASE ANY CPU  
MyTests - DEBUG ANY CPU  

Results:

Old:  DEBUG/DEBUG - 1 line missed  N-1/N % coverage  
New:  RELEASE/DEBUG - 0 lines missed, 100 % coverage   

Thank you John for pointing us in the right direction of looking at the IL.

like image 42
TheMightyGherkin Avatar answered Oct 18 '22 03:10

TheMightyGherkin