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)
Equivalent source in VB.NET: (yellow background indicates partial code coverage)
MSTests for both C# and VB.NET source (intended to achieve 100% code coverage)
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);
}
}
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With