Stubs in Microsoft Fakes

A few weeks back, I wrote an article about using shims in Microsoft Fakes. In addition to shims, Microsoft Fakes also has support for stubs. Stubs in Microsoft Fakes works a lot like other mocking frameworks such as Rhino Mocks, and it comes with a lot of the same limitations (must be visible, must be virtual, etc.). Let’s look at an example of what we can do using stubs in Microsoft Fakes. (Note: Microsoft Fakes requires Visual Studio 2012.)

Before we can use Microsoft Fakes, we need to do a little setup. Here are the steps that need to be performed:

  1. Create a new solution/project; I’m using a C# Console Application named “FakesSample”
  2. Add a new Unit Test Project to the solution; mine is named “FakesSample.Tests”
  3. Add a reference to the project to be tested in the test project
  4. In Solution Explorer, right-click the newly created reference and choose Add Fakes Assembly

And we’ll need some code to test. This is what I’ll be using:

namespace adamprescott.net.FakesSample
{
    using System;

    public class Mammal
    {
        public string Name { get; set; }
    }

    public interface IDataAccess
    {
        Mammal Get(int id);
    }

    public class Program
    {
        static void Main(string[] args)
        {
            var p = new Program();
            p.Run();
        }

        public IDataAccess DataAccess { get; set; }

        public void Run()
        {
            var m = DataAccess.Get(1);
            Console.WriteLine(m.Name);
        }
    }
}

Create a stub

The core functionality of a stub in unit tests is to remove external dependencies and/or provide makeshift functionality. In our code above, there is an IDataAccess that’s used to retrieve Mammal objects by ID. The Microsoft Fakes stub is perfect for this. In code, we create a Mammal object to be returned, and we return it using a lambda in our stub:

var m = new Mammal { Name = "Terry" };
var stubDataAccess = new StubIDataAccess
{
    GetInt32 = x => m
};

Verify a call

The stub gives us our desired behavior, but how do we know the stub was used? We can add verification by setting a flag in our stub implementation and asserting the value after the test is executed.

var m = new Mammal { Name = "Terry" };
var wasCalled = false;
var stubDataAccess = new StubIDataAccess
{
    GetInt32 = x => {
        wasCalled = true;
        return m;
    }
};
// ...
Assert.IsTrue(wasCalled);

I like that Microsoft Fakes makes this capability available without the need of a third party, but I’ll probably be sticking with Rhino Mocks for the time being. I haven’t found anything that I couldn’t do in MS Fakes that I could do with Rhino Mocks, but it often takes a lot more code. Maybe it’s because I’m less familiar with Fakes, or maybe it’s because Rhino Mocks is a more mature mocking framework–I’m not sure.

Here’s the complete unit test example:

namespace adamprescott.net.FakesSample.Tests
{
    using adamprescott.net.FakesSample.Fakes;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    [TestClass]
    public class ProgramTest
    {
        [TestMethod]
        public void RunWritesNameToConsole()
        {
            // Arrange
            var target = new Program();

            var m = new Mammal { Name = "Terry" };
            var wasCalled = false;
            var stubDataAccess = new StubIDataAccess
            {
                GetInt32 = x =>
                {
                    wasCalled = true;
                    return m;
                }
            };
            target.DataAccess = stubDataAccess;

            // Act
            target.Run();

            // Assert
            Assert.IsTrue(wasCalled);
        }
    }
}

Unit Testing and Private Methods

So you’re a TDD developer.  You code along merrily, writing failing unit tests, implementing them to a point of success, and then you refactor. But then, with no notice–WHAM–a private method. Now what!?

There are different schools of thought for this scenario. One camp says that if it’s not publicly exposed, you shouldn’t be testing it. I think that’s valid, but it’s equally valid to write test code for private methods. Just because a method’s private doesn’t mean it doesn’t deserve the same special attention. And just because I want to test a method that happens to be private doesn’t mean I want to expose it to the rest of the world! Let’s not worry about the debate for now. I’m going to show you how you can override private methods with Microsoft Fakes and how call private methods with Microsoft.VisualStudio.TestTools.UnitTesting.PrivateObject.

Override private methods

Problem: You have a private method with behavior that’s disruptive to unit testing. Regardless of the cause of the disruption, you want to provide an alternate implementation.

Solution: Use Microsoft Fakes to shim the private method. (Need to know more about Fakes? Check out my tutorial!)

Here’s how you can do it:

  1. Create an instance of your class
  2. Create a shim from  your class
  3. Override the private method on the shim
  4. Invoke the test method

Here’s a code example:

[TestMethod]
public void SecretMethod_FunctionalityIsOverridden()
{
    using (ShimsContext.Create())
    {
        var target = new FileReader("foo");
        var shim = new ShimFileReader(target);

        bool calledShimMethod = false;
        shim.SecretMethod = () => 
        {
            calledShimMethod = true;
            return "bar";
        };

        target.Read();

        Assert.IsTrue(calledShimMethod);
    }
}

Call private methods

Problem: You want to test a private method, but you can’t because it’s private.

Solution: Use Microsoft Test Framework’s included PrivateObject class.

The only thing I don’t like about PrivateObject is that it (presumably) uses reflection for method names, which means method names will be coded as strings with no compile-time checks. It’s very easy to use, though, and if you need to invoke a private method, I haven’t seen a better way to do it!

Here are the steps:

  1. Create an instance of your class
  2. Create a PrivateObject from your class
  3. Use the PrivateObject‘s Invoke method

And here’s the code:

[TestMethod]
public void SecretMethod_ReturnsHumorousMessage()
{
    var target = new FileReader("foo");
    var privateObject = new PrivateObject(target);
    var actual = privateObject.Invoke("SecretMethod");

    Assert.IsNotNull(actual);
}

Putting it all together (useless, but fun!)

I was able to verify both of these capabilities by writing a single unit test that overrides the private method, then calls the private method. Check it out:

[TestMethod]
public void SecretMethod_FunctionalityIsOverridden()
{
    using (ShimsContext.Create())
    {
        var target = new FileReader("foo");
        var shim = new ShimFileReader(target);

        // override the private method
        bool calledShimMethod = false;
        shim.SecretMethod = () => 
        {
            calledShimMethod = true;
            return "bar";
        };

        // call the private method
        var privateObject = new PrivateObject(target);
        var actual = privateObject.Invoke("SecretMethod");

        // assert that calling the private method
        // used the overridden implementation
        Assert.IsTrue(calledShimMethod);
    }
}

A “Shim-ple” Tutorial With Microsoft Fakes

I’ve written previously about using Rhino Mocks to write unit tests for hard-to-test code, but with the release of Visual Studio 2012 comes a new way to work around those not-so-test-friendly areas: Microsoft Fakes. For those of you familiar with Microsoft Research’s Moles project, Microsoft Fakes is simply the next version. Fortunately, Microsoft decided this offering was valuable enough to be included in the latest version of Visual Studio.

What is Fakes, you might be grammatically-awkwardly asking yourself. If I had to describe Microsoft Fakes in a sentence, I’d say this: Microsoft Fakes allows you to intercept any method call and provide a substitute implementation, including calls to static and non-virtual methods. Sounds powerful, right? Well, it is.

Getting started with MS Fakes is refreshingly easy, too. The integration with Visual Studio allows you to skip the hard parts and get right to the meat: hooking up the fakes to work with the code you’re testing. This post will show you how to write a unit test for a simple FileReader class that has a single Read method that–you guessed it–reads a file. I’ll walk you through the entire process from scratch to hopefully avoid any confusion. So let’s do it!

  1. Open Visual Studio 2012
  2. Create a new Visual C# Class Library project
  3. Create the FileReader class:
    namespace adamprescott.net.FakesTutorial
    {
        using System.IO;
    
        public class FileReader
        {
            private readonly string _path;
            public FileReader (string path)
    	    {
                _path = path;
    	    }
    
            public string Read()
            {
                using (var fs = new FileStream(_path, FileMode.Open))
                {
                    var sr = new StreamReader(fs);
                    return sr.ReadToEnd();
                }
            }
        }
    }
    
  4. Add a new Unit Test Project to the solution
  5. Add a reference to the Class Library project from the Unit Test Project
  6. Create the fakes assembly by right-clicking System in the Unit Test Project’s References and selecting “Add Fakes Assembly”
  7. Create the FileReaderTest class:
    namespace adamprescott.net.FakesTutorial.Tests
    {
        using Microsoft.VisualStudio.TestTools.UnitTesting;
    
        [TestClass]
        public class FileReaderTest
        {
            [TestMethod]
            public void TestMethod1()
            {
                using (Microsoft.QualityTools.Testing.Fakes.ShimsContext.Create())
                {
                    // Arrange
                    const string path = "irrelevant";
                    const string expected = "contents";
                    var target = new FileReader(path);
    
                    // shim the FileStream constructor
                    System.IO.Fakes.ShimFileStream.ConstructorStringFileMode =
                        (@this, p, f) => {
                            var shim = new System.IO.Fakes.ShimFileStream(@this);
                        };
    
                    // shim the StreamReader constructor
                    System.IO.Fakes.ShimStreamReader.ConstructorStream =
                        (@this, s) => {
                            var shim = new System.IO.Fakes.ShimStreamReader(@this) {
                                // shim the ReadToEnd method
                                ReadToEnd = () => expected
                            };
                        };
    
                    // Act
                    var actual = target.Read();
    
                    // Assert
                    Assert.AreEqual(expected, actual);
                }
            }
        }
    }
    
  8. Run the test, and feel great about yourself!

There are a few important things to note about the use of Fakes in the test above. First, the fakes are wrapped in a ShimsContext. This makes sense since you’re intercepting system calls; you don’t want to accidentally affect other areas being tested outside of your test. Next, note that I’m using fakes to override two different constructors. I needed to override FileStream‘s constructor to open the file and StreamReader‘s constructor to read the file. In the StreamReader shim, I also provide a shim for the ReadToEnd method and configure it to return the fake text for my test. I probably could have opted to shim just FileStream, but the faking might be less straightforward since success would rely on knowing exactly which methods StreamReader will use when ReadToEnd is called.

For more information about getting started with Microsoft Fakes, check out this article at MSDN.