Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I use Mock Objects in my unit tests and still use Code Coverage?

Presently I'm starting to introduce the concept of Mock objects into my Unit Tests. In particular I'm using the Moq framework. However, one of the things I've noticed is that suddenly the classes I'm testing using this framework are showing code coverage of 0%.

Now I understand that since I'm just mocking the class, its not running the actual class itself....but how do I write these tests and have Code Coverage return accurate results? Do I have to write one set of tests that use Mocks and one set to instantiate the class directly.

Perhaps I am doing something wrong without realizing it?

Here is an example of me trying to Unit Test a class called "MyClass":

using Moq;
using NUnitFramework;

namespace MyNameSpace
{
    [TestFixture]
    public class MyClassTests
    {

        [Test]
        public void TestGetSomeString()
        {
            const string EXPECTED_STRING = "Some String!";

            Mock<MyClass> myMock = new Mock<MyClass>();
            myMock.Expect(m => m.GetSomeString()).Returns(EXPECTED_STRING);

            string someString = myMock.Object.GetSomeString();

            Assert.AreEqual(EXPECTED_STRING, someString);
            myMock.VerifyAll();

        }

    }

    public class MyClass
    {
        public virtual string GetSomeString()
        {
            return "Hello World!";
        }
    }
}

Does anyone know what I should be doing differently?

like image 592
mezoid Avatar asked Dec 03 '08 05:12

mezoid


1 Answers

You are not using your mock objects correctly. When you are using mock objects you meant to be testing how your code interacts with other objects without actually using the real objects. See the code below:

using Moq;
using NUnitFramework;

namespace MyNameSpace
    {
        [TestFixture]
        public class MyClassTests
        {

            [Test]
            public void TestGetSomeString()
            {
                const string EXPECTED_STRING = "Some String!";

                Mock<IDependance> myMock = new Mock<IDependance>();
                myMock.Expect(m => m.GiveMeAString()).Returns("Hello World");

                MyClass myobject = new MyClass();

                string someString = myobject.GetSomeString(myMock.Object);

                Assert.AreEqual(EXPECTED_STRING, someString);
                myMock.VerifyAll();

            }

        }

        public class MyClass
        {

            public virtual string GetSomeString(IDependance objectThatITalkTo)
            {
                return objectThatITalkTo.GiveMeAString();
            }
        }

        public interface IDependance
        {
            string GiveMeAString();
        }
    }

It doesn't look like it is doing anything useful when your code is just returning a string without any logic behind it.

The real power comes if you GetSomeString() method did some logic that may change the result of the output string depending on the return from the IDependdance .GiveMeAString() method, then you can see how your method handles bad data being sent from the IDependdance interface.

Something like:

 public virtual string GetSomeString(IDependance objectThatITalkTo)
 {
     if (objectThatITalkTo.GiveMeAString() == "Hello World")
         return "Hi";
     return null;
 }

Now if you have this line in your test:

myMock.Expect(m => m.GiveMeAString()).Returns(null);

What will happen to your GetSomeString() method?

like image 114
Nathan W Avatar answered Oct 14 '22 07:10

Nathan W