如何在 Visual Studio 2010 Ultimate 中为 VB.NET 中的 "catch with rethrow" 块获得 100% 的代码覆盖率?

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

我的 VB.NET 源代码中的 "catch with rethrow" 块无法实现 100% 的代码覆盖率。我的工作场所 IDE 是 Visual Studio 2010 Ultimate。下面的例子代表了我实际问题的简化版本。

C# 中的源代码:(light-blue 背景表示完全代码覆盖)


VB.NET中的等效源:(黄色背景表示部分代码覆盖)


C# 和 VB.NET 源代码的 MSTest(旨在实现 100% 的代码覆盖率)


代码覆盖率报告


代码覆盖率报告显示 C# 为 100%,但 VB.NET 仅为 91.67%。它还显示了 1 个代码块,在 VB.NET 中发现了 0 行。

这是工具的问题吗?还是我遗漏了一些明显的东西?

编辑 #1: 根据@Raptor 的要求共享源代码

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));
      }
   }
}


源代码在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


MSTest 的源代码

[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);
   }
}

如果您在调试模式下查看为 VB 项目生成的 IL,您将在 catch 块中看到以下内容:

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

因为 IL_0039 抛出,你永远不会命中 IL_003a,所以你有永远不会被执行的代码。

在发布模式下,不会生成 ClearProjectError 的 IL。

没有足够的声誉来评论 John Koerner 的回复,这是正确的,但补充 - 我们通过让我们的测试目标 运行 处于发布模式来解决这个问题。这会导致代码覆盖率正常工作。

EG:

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

结果:

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

感谢 John 为我们指明了看待 IL 的正确方向。