RVP

Using Microsoft Fakes Part 2: Shims

On May 1, 2013, in .Net, Unit Testing, by admin

This is part 2 of Using Microsoft Fakes. If you missed the first one, check it out.

In the first part of this series I talked about using Stubs to unit test your code and they work great but sometimes you don’t have control over everything, you can’t exactly inject the System dll into your code. So how do you unit test logic that has a dependency on something you have don’t control over? Enter Shims.

Shims allow you to intercept a call at run time. This differs slightly from the stubs where we are passing in the stubbed out code. Very small difference, and the technique is very similar.

Using Shims

I am going to use the same example as in my previous post where I trying to test out some business logic for saving a person, but in this case I am going to be using as GUID as an identifier instead of an integer getting passed back from the data access layer.

        public Guid Save(Person p) {
            p.Name = "Changed Name";
            p.UniqueId = Guid.NewGuid();
 
            _personData.SavePerson(p);
            return p.UniqueId;
        }

So I don’t have control over the get new Guid. There is no way I can inject this functionality and no way that I can test to make sure a specific Guid gets assigned. I realize this is a bit contrived since you would never need to know a specific Guid gets generated, but hey this is just an example of usage, no one ever said it had to make sense!

Ok, so now that I have that disclaimer out of the way, let’s move onto the unit test code. Just as before I am going to inject the stubbed out version of IPersonData, but now I am now to put a shim in front of the new Guid.

using System;
using System.Fakes;
using Data;
using Data.Fakes;
using DataContracts;
using FakesTemp; //The name of my business logic class
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
 
namespace testProj {
    [TestClass]
    public class PersonTests {
        [TestMethod]
        public void PersonTests_HappyPath()
        {
            IPersonData personData = new StubIPersonData
            {
                SavePersonPerson = person => { return person.Age; }
            };
 
            PersonManager target = new PersonManager(personData);
 
            var p = new Person
                {
                    Age = 28,
                    Name = "Bruce Campbell"
                };
 
 
            Guid expected = new Guid("187695AC-1EE6-4BB4-BB71-366DBE9C8D0D");
            using (ShimsContext.Create())
            {
                ShimGuid.NewGuid = () => new Guid("187695AC-1EE6-4BB4-BB71-366DBE9C8D0D");
                Guid actual = target.Save(p);
                
                Assert.AreEqual(expected, actual);
            }
        }
    }
}

A few things to note. In order to generate the shim for the Guid.New I had to create a fakes assembly for the System dll. To do this you simply right click on the dll in your references folder in solution explorer and click on the add fakes assembly option. After that just add the using statement for the new System.Fakes assembly.

To get started using Shims, you must first create a ShimContext. This defines the scope for the shim, any shim that you create in this block will be used anywhere within the call. So if I had multiple calls to Guid.NewGuid() throughout the execution of my test they would all get the same Guid. So just keep in mind that using shims for built in code can cause some weird results if you aren’t careful.

In order to actually create the shim you simply preface whatever object you are shimming with the word shim. Take a second for that to sink in. That’s pretty much it. From there you define what specific method you are overriding, and then tell it what you want the value to be. Very very simple.

Summary

  • Using shims allows you to overwrite inbuilt methods at run time of your unit test
  • You should limit the scope of your shim to as narrow as possible to reduce the risk of unintended shimming
  • Combining both Stubs and Shims allows you to really isolate your code for testing
  • Unit testing is AWESOME!

This is also posted on my company blog

Tagged with:  
RVP

Using Microsoft Fakes Part 1: Stubs

On April 29, 2013, in .Net, Testing, Unit Testing, by admin

Starting with the release of Visual Studio 2012 Update 2 the Fakes framework is now available to use in both the Premium and Ultimate versions! HURRAY! Why am I so excited? Because this will allow me to unit test my code.

Now I know everyone doesn’t get as excited about unit testing code as I do but that’s ok. By the end of this 2 part series hopefully you will at least be a little excited, and realize that it isn;t as big of a chore as you may think.

The Fakes framework is based off of the moles and pex frameworks that we have been using for a while now. So what’s new in fakes? In terms of general usage, not a whole lot a lot of the changes are under the hood.

The biggest differences are:

  1. You don’t need to use the HostType Attribute
  2. Detours are referred to as Shims instead of Moles.
  3. Moles files are now fakes files

So a lot of things seem pretty cosmetic.

In this first post I will be talking about stubs, but before we do that let’s quickly discuss the difference between stubs and shims. You would use a stub when you are using a dependency injection pattern combined with sort of IOC container such as Unity.

You use a shim when you want to override the behavior of code that you really don’t have control over; something that you can’t pass in. So if you wanted to change the behavior of an inbuilt .Net method you could use shims to do that.

Using Stubs

In my example I have the following business logic code that I want to test out.

  public class PersonManager
    {
        private IPersonData _personData;
        public PersonManager(IPersonData personData)
        {
            _personData = personData;
 
        } 
  
        public int Save(Person p)
        {
            p.Name = "Changed Name";
 
            return _personData.SavePerson(p);
        }
    }

I am injecting my data access code in the constructor above, so this is a great example of when I want to use a stub. The code that I want to test is the Save method and as you can see there isn’t a whole lot there. But that is fine for our example.

In order to test this I first need to create my unit test project, just as you always have no changes there. The next step is to add all of your assemblies that you will need. In this case I need my data contracts, data access and my business logic layers in order to get this example working but the only thing that I need to fake would be my data access code since I want to isolate my business logic. In order to do that, assuming you have fakes installed, right click on your reference and click on add fakes assembly. Easy as that. I am now ready to write my unit test.

using System;
using Data;
using Data.Fakes;
using DataContracts;
using FakesTemp; //Name of my Buiness logic project
using Microsoft.VisualStudio.TestTools.UnitTesting;
 
namespace BusinessLogic.Tests {
    [TestClass]
    public class PersonTests {
        [TestMethod]
        public void PersonTests_HappyPath()
        {
            IPersonData personData = new StubIPersonData {
                SavePersonPerson = person => { return person.Age; }

            };
 
            PersonManager target = new PersonManager(personData);
 
            var p = new Person
                {
                    Age = 28,
                    Name = "Bruce Campbell"
                };
 
            int expected = 28;
            int actual = target.Save(p);
 
            Assert.AreEqual(expected, actual);
        }
    }
}

If you have been using Moles for a while, this shouldn’t look very different to you. The only major difference would be using the StubIPersonData instead of SIPersonData that you would see if you were using Moles.

Taking a closer look at StubIPersonData we can see that we are stubbing out the SavePerson method that my business logic above is calling. So why is it called SavePersonPerson? The second ‘Person’ is the type of argument I am passing in. For example if I was passing a string into the method the stub would look like SavePersonString.

The next part is where I am declaring the parameters I am passing in, in this case person. This will catch whatever I am passing in and I can then manipulate the object in my stub if I need to. In this example I am just going to return whatever the person’s age is just to prove that point, but you can return any integer that you wish, since that is the return type of the SavePerson method.

From there you just create the class you are testing, by convention named target, and pass in your stubbed out IPersonData interface. Then create a Person object to pass into my save method, and then actually call the save method and capture the result. I am expecting to get back the age of the person, so I want to assert that is actually what I am getting back.

Taking it further

So in the example above, I am only stubbing out one method in one class, but you can stub any number of classes and any number of methods inside of those classes. Just because the method exists in your interface however doesn’t mean that you have to stub it if the method you are testing doesn’t use it. There is no reason to add clutter in your code.

Summary

  • Fakes are now available to users in both the Ultimate and Premium versions of Visual Studio 2012 assuming you have update 2 installed.
  • Fakes assemblies allow you to either create stubs or shims
  • Stubs allow you to override implementations of classes you pass in using an IOC container or something similar.
  • Shims allow you to override built in classes (or classes you don’t have control over) at run time.
  • Unit testing is AWESOME!

Look for part two of this series where we are going to talk about using shims!

This is also posted on my company blog!

Tagged with: