Skip to content
Bruno Sonnino
Menu
  • Home
  • About
Menu

Testing the untestable with Microsoft Fakes

Posted on 11 August 2013

Introduction

Sometimes you must do some changes on legacy programs that were not built using good development practices. At that time, our first reaction is to run away from that: the probability of having problems is too high and touching the source code is almost impossible - we are working on a castle of cards, where even the slightest move can bring everything down.

The idea of refactoring (or even rewrite) the code comes from a long time, but where is the time to do that? All projects are late and that's not a priority, its working, no? Why touch on that?

We can make the situation a little better by creating unit tests for the changes we must do, but how to do that? The program is full of dependencies, the business rules are mixed with the views, and the methods are long and complicated.

The best we could do are integration tests, that are difficult to implement and slow to execute, they will be abandoned very soon. What to do now? The solution is at hand, Microsoft implemented a Microsoft Research's project, named Moles, and put it in Visual Studio 2012 with the name of Fakes, so we can create test for anything, including .Net Framework classes.

With Fakes we can create unit tests that run fast and don't depend of anything, nor operating system, machine or database. Here I must do a note: although Fakes can test almost anything, that's not an excuse to relax our coding style - you must use good programming practices on the new code and do not rely on Fakes to simulate dependencies that should not exist. When you are creating new code, try to do it in a way that you don't need Fakes, use it only where that is really needed.

The problem

To show how to use Fakes, we will create a small WPF project that has a window with a TextBlock:

 <Window x:Class="FakesTest.MainWindow"  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
     Title="MainWindow" Height="350" Width="525">  
   <Grid>  
     <TextBlock x:Name="TxtDate"/>  
   </Grid>  
 </Window>  
XML

When the window is initialized, the TextBlock is fed with the current date:

 public partial class MainWindow  
 {  
   public MainWindow()  
   {  
     InitializeComponent();  
     TxtDate.Text = string.Format(  
      "The current date is {0:d}", DateTime.Now);  
   }  
 }  
C#

We should change this code to put the weekday in the TextBlock, like in "The current date is 8/2/2013 (Friday)". We want to use best practices and will create unit tests for the project. But how to do it? The code is mixed with the View and has a dependency on DateTime, a .Net Framework class.

Creating the test project

The first step is to create the test project. On the Solution Explorer, select the solution and right click it, selecting Add/New Project. Select Test/Unit Test Project and call it FakesTest.Tests. Add to it a reference to our project. Rename the UnitTest1.cs class to MainWindowTests.cs.

Here starts our problem: we want to test what is being shown in the TextBlock. For that, we must create a window, initialize it and look at its content. Not an easy task to do with unit tests.

Here comes Fakes to rescue. On the test project, on the references, select the reference to the main project and select Add Fakes Assembly. A new reference to FakesTest.Fakes is added - this reference will create all fakes for the window and its componentes. To use it on our tests, we must add the references to System.Xaml, PresentationCore, PresentationFrameworkand WindowsBase.

The next step is to create a fake for the DateTime class. Select the System assembly in the references and right click it, selecting Add Fakes Assembly. Now that we have all our environment "virtualized", we can start creating tests.

To use the components created by Fakes we must surround the calls in a context, with the keyword Using, using a ShimsContext:

 using (ShimsContext.Create())  
 {  
   ….  
 }  
C#

Inside the context, we must tell the behavior of the fake DateTime class, when the method Now will be called:

 ShimDateTime.NowGet = () => new DateTime(2013,1,1);  
C#

To access the DateTime class created by Fakes, we must use the ShimDateTime class. The line above tells us that when the getter of the Now property is called (NowGet), it must return 1/1/2013. From now on, the test becomes exactly the same as any other unit test:

 [TestMethod]  
 public void CreateWindow_TextBlockHasCurrentDate()  
 {  
   using (ShimsContext.Create())  
   {  
     ShimDateTime.NowGet = () => new DateTime(2013,1,1);  
     var window = new MainWindow();  
     var mainGrid = (Grid)window.Content;  
     var textBlock = (TextBlock) mainGrid.Children[0];  
     Assert.AreEqual("The current date is 01/01/2013",textBlock.Text);  
   }  
 }  
C#

We have created the window and verified if the TextBlock has the date we have passed on the fake. When we execute the tests with Ctrl+R+T, we see that the test passes. We are covered here, and we can make the changes we need on our code.

Changing the program

As we already have the test, we can change it for the new feature we want:

 [TestMethod]  
 public void CreateWindow_TextBlockHasCurrentDate()  
 {  
   using (ShimsContext.Create())  
   {  
     ShimDateTime.NowGet = () => new DateTime(2013,1,1);  
     var window = new MainWindow();  
     var mainGrid = (Grid)window.Content;  
     var textBlock = (TextBlock) mainGrid.Children[0];  
     Assert.AreEqual(  
      "The current date is 01/01/2013 (Tuesday)",textBlock.Text);  
   }  
 }  
C#

We have made the change on the test but not on the code. If we run our test now, it will fail:

 Assert.AreEqual failed. Expected:<The current date is 01/01/2013 (Tuesday)>. Actual:< The current date is 01/01/2013>.  
Plain text

We must change the code:

 public MainWindow()  
 {  
   InitializeComponent();  
   TxtDate.Text = string.Format(  
    "The current date is {0:d} ({0:dddd})", DateTime.Now);  
 }  
C#

When we execute the test, it passes - our change is complete and working. To complete the Red-Green-Refactor cycle from TDD, we can refactor the code, extracting the function from where we set the TextBlock:

 public MainWindow()  
 {  
   InitializeComponent();  
   TxtDate.Text = GetTextDate();  
 }  
 private static string GetTextDate()  
 {  
   return string.Format(  
    "The current date is {0:d} ({0:dddd})", DateTime.Now);  
 }  
C#

We run the tests and they still pass. The change is finished.

Conclusions

As we can see, Fakes helps a lot when we have legacy code that, for its dependencies, don't allow creating unit tests in an easy way. What we have done here is to simulate the creation of a window and assign a value to a TextBlock, passing the current date with no special arrangement.

We are not advocating using this resource always - you should use Fakes only as the last resource, when the code is already there and there is not an easy way to break it. It can be used as a starting point for the real refactoring of the program: in this case, we must remove the window dependencies using the MVVM pattern and also from the System.DateTime, using some kind of wrapper interface (that we could call as IDateTimeProvider), but this is a subject for another article!

1 thought on “Testing the untestable with Microsoft Fakes”

  1. Pingback: Restructuring your legacy code using MVVM and Dependency Injection with Unity – Bruno Sonnino

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

  • May 2025
  • December 2024
  • October 2024
  • August 2024
  • July 2024
  • June 2024
  • November 2023
  • October 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • June 2022
  • April 2022
  • March 2022
  • February 2022
  • January 2022
  • July 2021
  • June 2021
  • May 2021
  • April 2021
  • March 2021
  • February 2021
  • January 2021
  • December 2020
  • October 2020
  • September 2020
  • April 2020
  • March 2020
  • January 2020
  • November 2019
  • September 2019
  • August 2019
  • July 2019
  • June 2019
  • April 2019
  • March 2019
  • February 2019
  • January 2019
  • December 2018
  • November 2018
  • October 2018
  • September 2018
  • August 2018
  • July 2018
  • June 2018
  • May 2018
  • November 2017
  • October 2017
  • September 2017
  • August 2017
  • June 2017
  • May 2017
  • March 2017
  • February 2017
  • January 2017
  • December 2016
  • November 2016
  • October 2016
  • September 2016
  • August 2016
  • July 2016
  • June 2016
  • May 2016
  • April 2016
  • March 2016
  • February 2016
  • October 2015
  • August 2013
  • May 2013
  • February 2012
  • January 2012
  • April 2011
  • March 2011
  • December 2010
  • November 2009
  • June 2009
  • April 2009
  • March 2009
  • February 2009
  • January 2009
  • December 2008
  • November 2008
  • October 2008
  • July 2008
  • March 2008
  • February 2008
  • January 2008
  • December 2007
  • November 2007
  • October 2007
  • September 2007
  • August 2007
  • July 2007
  • Development
  • English
  • Português
  • Uncategorized
  • Windows

.NET AI Algorithms asp.NET Backup C# Debugging Delphi Dependency Injection Desktop Bridge Desktop icons Entity Framework JSON Linq Mef Minimal API MVVM NTFS Open Source OpenXML OzCode PowerShell Sensors Silverlight Source Code Generators sql server Surface Dial Testing Tools TypeScript UI Unit Testing UWP Visual Studio VS Code WCF WebView2 WinAppSDK Windows Windows 10 Windows Forms Windows Phone WPF XAML Zip

  • Entries RSS
  • Comments RSS
©2025 Bruno Sonnino | Design: Newspaperly WordPress Theme
Menu
  • Home
  • About