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

48,251

Solution 1

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?

Solution 2

Big mistake is mocking the System Under Test (SUT), you test something else. You should mock only SUT dependencies.

Solution 3

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.

Share:
48,251
user3953201
Author by

user3953201

A C# .NET Developer with a passion for coding best practices and Test Driven Development

Updated on November 10, 2020

Comments

  • user3953201
    user3953201 over 3 years

    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?

  • Adam Short
    Adam Short over 6 years
    Missing a bracket in your GetSomeString example after the parameter.