views:

323

answers:

4

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?

+2  A: 

Big mistake is mocking SUT, you test something else. You should mock only SUT dependencies.

rarouš
+7  A: 

You not using you 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();
        }
    }

I 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";
            }

Now if you have this line in your test:

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

What will happen to your GetSomeString() method?

Nathan W
A: 

That makes a lot of sense. Essentially you're saying that I need to be doing the following:

public class MyClass
{
    public virtual string GetSomeString(MyOtherClass moc)
    {
        return moc.ToString();
    }
}

.....

Mock<MyOtherClass> myMock = new Mock<MyOtherClass>();

MyClass mc = new MyClass();

string someString = mc.GetSomeString(myMock.Object);
Assert.AreEqual(EXPECTED_STRING, someString);

Essentially instantiating the SUT and only using mocks for the classes the SUT requires?

mezoid
Plus your GetSomeString method will now have coverage because you are calling the real GetSomeString but just with a fake object it needs so your not going any deeper and launching any missiles that you don't know about :) Its all about testing in isolation.
Nathan W
A: 

I would recommend staying away from mocking frameworks until you understand the interactions that are going on here.

IMO it's better to learn with manually created test doubles, then graduate to a mocking framework afterwards. My reasoning:

  1. Mocking frameworks abstract away what's actually happening; it's easier to grasp the interactions if you have to create your dependencies explicitly, then follow the tests in the debugger.

  2. It's easy to misuse frameworks. If you roll your own when you're learning, you are more likely to understand the differences between different type of test doubles. If you go straight to a mocking framework, it's easy to use mocks when you wanted stubs and vice versa -- there is a big difference.

Think of it this way: The class under test is the focus. You create an instance of it, call its methods and then assert that the result is correct. If the class under test has dependencies (e.g. something is required in the constructor), you satisfy those dependencies using either A: real classes or B: test doubles.

The reason we use test doubles is that it isolates the class under test, meaning that you can exercise its code in a more controlled fashion.

E.g. if you have a class that contains a network object, you cannot test the owning class's error handling routines that detect dead connections if you're forced to use a concrete network connection object. Instead, you inject a fake connection object and tell it to throw an exception when its "SendBytes" method is called.

I.e. In each test, the dependencies of the class under test are created specifically to exercise a particular piece of code.

Mark Simpson