2

I'm using Visual Studio 2010 Ultimate SP1. I have around 225 unit tests in my project, and they are all passing. One of those tests, however, reports 0% code coverage for the method it hits. When debugging, I can step through and see that it hits every line of the method. Yet in the code coverage report, it shows that the method isn't covered at all. All other tests and methods work just fine with regards to code coverage.

I've tried the following with no success:

  • Moved the method being tested into another class.
  • Made the method
  • static vs. non-static.
  • Moved the test to another class.
  • Deleted all of my .testsetting files and recreated them from scratch
  • Wrote a different test to exercise the same method, with the same results
  • restarted VS
  • rebooted

In case it matters, the method was in the Global.asax file. However, I moved it to another class and it made no difference.

Any ideas?

Here is the method being tested.

 public void LogError(ILoggingService loggingService, IController controller)
    {
        if (loggingService == null)
            throw new ArgumentNullException("loggingService");

        if (controller == null)
            throw new ArgumentNullException("controller");

        Exception ex = Server.GetLastError();

        loggingService.LogException(ex.Message, ex.StackTrace, ApplicationName.VoucherLog, UserInfo.UserName);


        HttpException httpException = ex as HttpException;

        if (httpException == null)
        {
            var routeData = new RouteData();
            routeData.Values["controller"] = "Error";
            routeData.Values["action"] = "HttpError";

            Server.ClearError();

            var rc = new RequestContext(new HttpContextWrapper(Context), routeData);
            controller.Execute(rc);
        }
    }

The first 4 lines, where the exceptions are thrown, are hit by other tests and show up in the code coverage statistics. The remainder of the method is hit by the following test (as verified by debugging through it and seeing that each and every line is, in fact, executed), but does not show up in code coverage stats. Here is the test:

    [TestMethod]
    [HostType("Moles")]
    public void LogError()
    {
        DMVCommon.ApplicationName expectedApplication = DMVCommon.ApplicationName.VoucherLog;
        string expectedUser = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
        NotImplementedException expectedException = null;

        System.Web.Moles.MHttpServerUtility.AllInstances.GetLastError = (System.Web.HttpServerUtility server) =>
        {
            return expectedException;
        };

        System.Web.Moles.MHttpApplication.AllInstances.ContextGet = (System.Web.HttpApplication application) =>
        {
            return MvcMockHelpers.FakeHttpCurrentContext();
        };


        try
        {
            throw new NotImplementedException();
        }
        catch (NotImplementedException exc)
        {
            expectedException = exc;
            using (MvcApplication app = new MvcApplication())
            {
                bool called = false;

                Mock<ILoggingService> mockLoggingService = new Mock<ILoggingService>();
                mockLoggingService.Setup(a => a.LogException(expectedException.Message, expectedException.StackTrace, expectedApplication, expectedUser)).Callback(() => called = true);

                Mock<IController> mockController = new Mock<IController>();

                app.LogError(mockLoggingService.Object, mockController.Object);

                mockController.Verify(a => a.Execute(It.IsAny<System.Web.Routing.RequestContext>()), Times.Exactly(1));
                Assert.IsTrue(called);
            }
        }
    }
jvaran
  • 55
  • 6
  • Are you running coverage in RELEASE? Can you show us the method itself? – seldary Apr 30 '12 at 05:30
  • I was running in DEBUG. However, after you asked I tried again in RELEASE, and the results were no different. I updated the question with the code, both for the test and the method being tested. We're using Moq and Moles, by the way. – jvaran Apr 30 '12 at 14:10

1 Answers1

0

This happens probably because of your usage of Moles - As the runner loads the assembly, Moles takes over and profiles the assembly instead of the coverage profiler.

There has been known integration issues with coverage tools and Moles - In order for two .Net profilers (Moles & coverage) to work together they have to implement specific support for each other.

Try to run without Moles and see what happens...

Also see this as a similar example.

Community
  • 1
  • 1
seldary
  • 6,186
  • 4
  • 40
  • 55
  • Yes, that was it! When I commented out the lines that were being moled and the moles in the test, it all worked as expected. So I guess my best course of action right now is to just add the [ExcludeFromCodeCoverage] attribute to the method, along with a comment explaining that it is actually covered and why? My only concern is that future code changes that may change the coverage won't necessarily be noticed. – jvaran May 01 '12 at 12:47