Translate

Friday, July 25, 2014

Microsoft shims for faking methods

If you want to inject some fake code for testing, there are two ways to do it. Stubs and Shims.



Stubs can be achieved using dependency injection. Microsoft provides the unity framework to facilitate dependency injection. I personally prefer autofac for dependency injection.

If your code was not written keeping testability in mind, then you may not be able to use stubs. That's where shims come in. A shim modifies the compiled code of your application at run time so that instead of making a specified method call, it runs the shim code that your test provides. Shims are also useful when you want to fake something in a third party assembly.

Note: Fakes are available only in VS Ultimate.

In the example below, I will be testing a method that returns current year +1.

 class MyClassToBeTested
    {
        public static int ReturnCurrentYearPlusOne()
        {
            return System.DateTime.Now.Year+1;
        }
    }

As you can see, if I want System.DateTime.Now to return 1/1/2000, its not possible. Unless I fake it.

This is how you do it

1>Add references to 
  • c:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies\Microsoft.QualityTools.Testing.Fakes.dll
  • c:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\PublicAssemblies\Microsoft.VisualStudio.QualityTools.UnitTestFramework.dll
2>Right click on the reference System and click "Add Fakes Assembly"





































3>Paste the code below into a class file

using System;
using System.Fakes;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;
 
namespace ShimPlay
{
    [TestClass]
    public class ShimPlayClass
    {
        [TestMethod]
        public void TestMethod()
        {
            int nextYear = MyClassToBeTested.ReturnCurrentYearPlusOne(); //returns 2015 (current year is 2014)
 
            using (ShimsContext.Create())
            {
               //The faking happens only inside this using block
               ShimDateTime.NowGet = () => new DateTime(2000, 1, 1);
               int nextYearFake = MyClassToBeTested.ReturnCurrentYearPlusOne();//returns 2001
            }
        }
    }
 
    internal class MyClassToBeTested
    {
        public static int ReturnCurrentYearPlusOne()
        {
            return DateTime.Now.Year + 1;
        }
    }
}


No comments:

Post a Comment

Comments will appear once they have been approved by the moderator