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.

Advertisements

15 thoughts on “A “Shim-ple” Tutorial With Microsoft Fakes”

    1. Hmm, I’m not sure how to help. My first thought was that maybe the option was only available to a “Unit Test” project type, but I opened up a VS2012 solution and verified that the option was available in unit test projects, class libraries, and web projects. There doesn’t seem to be any limitation on project type.

      Is the option only missing for System, or does it show for other references?

      1. If I’m not mistaken, the Fakes capability is only offered in the Ultimate version. If you’re using another version, you probably don’t have access to Fakes for that reason.

  1. Thanks bro!! i’ve been trying to learn how to use Fakes and Shims and you provide well info’d tutorials that are simple yet can go a long way! (if that makes sense lol)

  2. mark rogers – Kenn is right; Fakes were shipped only with Ultimate. However in VS 2012 Update 2 they extended the Fakes feature to Premium, which is what I have. Applying the update caused the Add Fakes Assembly option to magically appear.

    hope this helps …

    1. Give this a shot:


      private IDisposable _shimsContext;

      [TestInitialize]
      public void TestInitialize()
      {
      _shimsContext = ShimsContext.Create();
      }

      [TestCleanup]
      public void TestCleanup()
      {
      _shimsContext.Dispose();
      }

  3. Hey there. Apologies for necro’ing this. I’m a somewhat experienced Fakes user but am having trouble using fakes specifically with the class you used (ShimFileStream). It builds just fine but I get a runtime error: System.TypeLoadException: Could not load type ‘System.IO.Fakes.ShimFileStream’ from assembly ‘mscorlib.4.0.0.0.Fakes, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0ae41878053f6703’.

    I’m also unable to shim File, but am able to successfully shim other classes in mscorlib (specifically System.DateTimeOffset and System.Collections.ArrayList were the two I tried).

    Any thoughts?

Leave a comment

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s