Click here to Skip to main content
15,883,731 members
Articles / Programming Languages / C# 4.0

Unit testing with Fakes with Visual studio Premium 2012

Rate me:
Please Sign up or sign in to vote.
4.75/5 (14 votes)
25 Apr 2013CPOL4 min read 74.9K   1.7K   27   2
Dummy's guide to Fakes.

 

Introduction

 

What is Fakes 

  Microsoft Fakes framework, helps you to test your code, when you want to use some external variables whose values change randomly (like stocks) and you are using that in your code (you want to test this code, without bothering about the external factors). Another case could be testing something which i not yet complete.

So in your code you have something which you want to test + Some external factors.

Fakes would help you by replacing external factors by your code.

The need

- You want to test an undeveloped functionality.  

- You want to test something which returns different values at different times. For example you want to find the version of an Android on a mobile device deployed in field. You have a web service which finds the version. Now you want to do some tests which should get all the versions and then test something for all these versions. You use Fakes here as you are not interested in the testing of the webservice but in the testing of various versions returned by the webservice.

Fakes replaces the original functionality with something called Stubs Or with Shims  

Stubs: Replace the functionality written by you with stubs. Remember for you to use Stubs, you should have interface based programming i.e. you cannot directly instantiate a class, instead you should be using the interface (which helps in replacing the original functionality with the stub, based on the same interface).

Shims: Replace the functionality provided by .NET framework by Shims.  

Important considerations (refer http://msdn.microsoft.com/en-us/library/hh549175%28v=vs.110%29.aspx)

 

Performance. Shims run slower because they rewrite your code at run time. Stubs do not have this performance overhead and are as fast as virtual methods can go.

Static methods, sealed types. You can only use stubs to implement interfaces. Therefore, stub types cannot be used for static methods, non-virtual methods, sealed virtual methods, methods in sealed types, and so on.

Internal types. Both stubs and shims can be used with internal types that are made accessible by using the assembly attribute InternalsVisibleToAttribute.

Private methods. Shims can replace calls to private methods if all the types on the method signature are visible. Stubs can only replace visible methods.

Interfaces and abstract methods. Stubs provide implementations of interfaces and abstract methods that can be used in testing. Shims can’t instrument interfaces and abstract methods, because they don’t have method bodies.

 

Difficulties

I had a VS2012 Premium and had difficulties in using Fakes then got the below link. 

http://connect.microsoft.com/VisualStudio/feedback/details/746742/fakes-framework-is-not-available-in-vs12-premium

On further digging was able to find that VS Update 2 could be of help.  

http://blogs.msdn.com/b/bharry/archive/2013/01/30/announcing-visual-studio-2012-update-2-vs2012-2.aspx

 

Using the code

We have a console application called "LearningFakes". Now unit testing is testing the smallest block of code we have. We discussed earlier that for using Fakes we should be working on Interfaces (which gives us various other design benefits):  

We have the following interface (IUpgradeService.cs) and we want to stub currentSWVersion. The real implementation is placed in another file (UpgradeService.cs).

 
C++
/// <summary>
/// Check the current device version check if upgrades are required, check last upgrade date etc.
/// </summary>
public interface IUpgradeService
{
    int currentSWVersion(int x);
    bool isSWUpgradeRequired(int DeviceID);
    DateTime lastUpgradeDate(int DeviceID);
    bool upgradeDevice(int DeviceID);
}
 

The implementation of this interface is in "UpgradeService.cs".

 
C++
/// <summary>
/// Dummy functionlity always returns 5.
/// </summary>
/// <param name="DeviceID"></param>
/// <returns></returns>
public int currentSWVersion(int DeviceID)
{
    // Check the version and return the version, hard coded to 5 for ease in understanding.

    return 5;
}
 

Creating Unit Test for testing the currentSWVersion.

 

The following is how you would write a unit test when not using fakes. Here if we are testing a device with version 5 then we are good, if we are testing device with any other version then we would see a test failure.

 
C++
namespace UnitTestFakes
{
    [TestClass]
    public class WithoutFakes
    {
        [TestMethod]
        public void TestCurrentSWVersion()
        {
            int expected = 5;
            UpgradeService us = new UpgradeService();
            int actual = us.currentSWVersion(1);
            Assert.AreEqual(expected, actual, "Same Versions found");

        }
    }
} 

  Unit testing using Fakes (STUBS)

Step1: Add the assembly for which you are writing (stubbing) test cases to the test project.

Step2: Add fakes Assembly for the assembly in test. You just need to right click and select appropriate item in the context menu.

Image 1

Step 3:  You should see the below additions after adding the assembly

Image 2

 

Step 4: Add unit test for the CurrentSWUpgrade method.


C++
namespace UnitTests
{
    [TestClass]
    public class TestUpgradeService
    {        
        [TestMethod]
        public void TestCurrentSWVersion()
        {
            int expected = 10;
            IUpgradeService us = new LearningFakes.Fakes.StubIUpgradeService()
                { 
C++
                    // Definitions for multiple methods can be combined by separating by commas.
                    CurrentSWVersionInt32 = (DeviceID) => { return 10;},
                    IsSWUpgradeRequiredInt32 = (DeviceID) => { return true; }
                };
            int actual = us.currentSWVersion(1);
            Assert.AreEqual(expected, actual, "Same Versions found");

        }
    }
}  

 In the above code we can see that

a) How the interfaces are in use, we can clearly see that with interfaces Fakes would have been impossible.

b) We can see that we are creating Stub methods.

c) Multiple stub methods can be combined using comma separator.

Step 5: Checking the definition of StubIUpgradeService, go to the definition by placing cursor under the bold below and press F12 

C++
IUpgradeService us = new LearningFakes.Fakes.StubIUpgradeService() 

  Image 3

You will notice that

a) this class derives for the initial IUpgradeService.

b) We are using Func, delegate which "Encapsulates a method that has one parameter and returns a value of the type specified by the TResult parameter".

Refer:

http://msdn.microsoft.com/en-in/library/bb549151.aspx 

 

Unit testing using Fakes (SHIMS)

While testing, you may have instances where you have classes instead of interfaces. Or you want to test framework functionality. You will be using SHIMS in these scenarios.

The following is a simple scenario (where we want to get the date).

Code

 We want to test some scenario dependent of the current date, but because current date is different all the times, testing can be difficult and can be eased by using SHIMS.

C++
public DateTime lastUpgradeDate(int DeviceID)
        {
            // The datetime is dependent on the device in field.
            return DateTime.Now;            
        }  

Approach 

a) Add Fakes for System.dll

Image 4

b)  Add unit test. 

C++
[TestMethod]
public void TestLastUpgradeDate()
{
    using (ShimsContext.Create())
    {
        System.Fakes.ShimDateTime.NowGet =
        () =>
        { return new DateTime(2010, 11, 5); };
        var fakeTime = DateTime.Now; // It is always DateTime(2010, 11, 5);
        Console.WriteLine(fakeTime.ToShortDateString());
    }
    var correctTime = DateTime.Now;
    Console.WriteLine(correctTime.ToShortDateString());
}

You will notice

- The date time is faked inside the ShimsContext.  ShimContext controls the lifetime of the object.

- You get the current DateTime outside the ShimsContext Scope.

 


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
More about me on my website
http://lalit.50webs.com

Comments and Discussions

 
Questionhi help me Pin
Member 1213853913-Nov-15 20:46
Member 1213853913-Nov-15 20:46 
QuestionMocks are better then Stubs Pin
kranthikumar_kvs3-May-13 0:13
kranthikumar_kvs3-May-13 0:13 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.