C# Unit Test with Microsoft Fakes (2024)

Posted on In C# Disqus:
Symbols count in article: 931 Reading time ≈ 3 mins.

In common C# Unit test, we always meet the problem that our final application is depending on many 3rd party or system references. But for unit test, we need to separate and control the dependency libraries behaviour. One of the solution will be Microsoft Fake.

Here let me talk about Microsoft Fake , and how to unit test your application which depends on many system or other references.

Microsoft Fake

Microsoft Fakes is a test framework help you isolate the code you are testing by replacing other parts of the application.
Microsoft Fake is highly integrated with Visual Studio and you can easily start to use it with very several clicks.

Fakes come in two flavours:

A good diagram to distinguish those two:
C# Unit Test with Microsoft Fakes (1)

ComparisonShimStub
PerformanceSlow ( rewrite code )As it is ( just interface implementation )
Static method, seal type✔✗
Internal Type with InternalsVisibleToAttribute✔✔
Private methods✔ if all the types on the method signature are visible✗
Interfaces and abstract methods✗✔

Using Shim

Here let we say that we want to test a function in a DemoClassLibrary.

We have a class that implements something depends on System library.

1
2
3
4
5
6
7
8
9
10
11
12
13
using System;

namespace DemoClassLibrary
{
public class Foo
{
public long UtcNowTick()
{
return DateTime.UtcNow.Ticks;
}
}
}

So this UtcNowTick is depends on the DateTime, and right now we want to test this function.

This is a typical scenario for us to use shim to test because we cannot control the behaviour of the system library.

First, we add the fake to the library to we want to fake.
C# Unit Test with Microsoft Fakes (2)

After this operation, we can find that we have a fake assembly created:
C# Unit Test with Microsoft Fakes (3)

So right now, we have the fake assembly for system now, and we can control the behaviour of system namespace api as below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
using DemoClassLibrary;
using Microsoft.QualityTools.Testing.Fakes;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ClassLibaryTest
{
[TestClass]
public class TestFoo
{
[TestMethod]
public void TestUtcNowTick()
{
using (ShimsContext.Create())
{
System.Fakes.ShimDateTime.UtcNowGet = () =>
{
return DateTime.MinValue;
};


var foo = new Foo();
var tick = foo.UtcNowTick();

Assert.AreEqual(tick,0);
}
}
}
}

As the code show, the fake framework will add an extra code for your faked namespace (such as system in our demo), and all the extra code will under Fakes namespace.
We can replace function calls under Fakes namespace to our test implementation expected. Every type will have a Shim+Typename under Fakes for us to replace.

** There is some kinds of different scenarios which we need to test using Shim, here I list some:**

Let’s say that we have a 3rd party library like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace DemoDependence
{
public class DependenceClass
{
private readonly string _data;

public DependenceClass(string data)
{
_data = data;
}


public static string StaticMethod()
{
return "DependenceClass::StaticMethod ";
}

public string InstanceMethod()
{
return "DependenceClass::InstanceMethod " + _data;
}
}
}

And we have our application that use this library:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using System;
using System.Globalization;
using DemoDependence;

namespace DemoClassLibrary
{
public class Foo
{
public string UseDependencyInstanceMethod()
{
var instance = new DependenceClass(
DateTime.UtcNow.ToString(CultureInfo.CurrentCulture));
return instance.InstanceMethod();
}

public string UseDependencyStaticMethod()
{
return DependenceClass.StaticMethod();
}

public string UseOneDependencyInstanceMethod(DependenceClass d)
{
return d.InstanceMethod();
}


public string UseConstructor(string d)
{
var instance = new DependenceClass(d);
return instance.InstanceMethod();
}

}
}

we start our test.

shim static function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
[TestMethod]
public void ShimStaticMethod()
{
using (ShimsContext.Create())
{
ShimDependenceClass.StaticMethod =
() =>
{
return "my string";
};

var foo = new Foo();

Assert.AreEqual(foo.UseDependencyStaticMethod() , "my string");

}
}

shim instance function

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
[TestMethod]
public void ShimInstanceMethod()
{
using (ShimsContext.Create())
{
ShimDependenceClass.AllInstances.InstanceMethod =
@class =>
{
return "my string";
};

var foo = new Foo();

Assert.AreEqual(foo.UseDependencyInstanceMethod(), "my string");
}
}

[TestMethod]
public void ShimOneInstanceMethod()
{
using (ShimsContext.Create())
{
var d = new ShimDependenceClass()
{
InstanceMethod = () => { return "my string"; }
};


var foo = new Foo();

Assert.AreEqual(foo.UseOneDependencyInstanceMethod(d), "my string");

}
}

shim constructor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
[TestMethod]
public void ShimConstructor()
{
using (ShimsContext.Create())
{
ShimDependenceClass.ConstructorString =
(@this, s) =>
{
var shim = new ShimDependenceClass(@this)
{
InstanceMethod = () => { return "my string"; }
};
};

var foo = new Foo();

Assert.AreEqual(
foo.UseConstructor(string.Empty),
"my string");

}
}

Using Stub

Stum is typically using to implement the interface, let say we have a interface:

1
2
3
4
public interface IDependenceInterface
{
string InterfaceMethod();
}

And our Foo has one more function:

1
2
3
4
5
6
7
8
9
public class Foo
{
// Hide others

public string UseInterface(IDependenceInterface i)
{
return i.InterfaceMethod();
}
}

The stub would be like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[TestMethod]
public void StubInterface()
{
var i = new StubIDependenceInterface()
{
InterfaceMethod = () => { return "my string"; }
};


var foo = new Foo();

Assert.AreEqual(
foo.UseInterface(i),
"my string");
}

Compile warning issue

When you use fake the System library, you may see the compilation warning, that is because some type cannot be fakes, you can change the fake configuration file to fixit.
The warning is like below:

Warning 20 Some fakes could not be generated. For complete details, set Diagnostic attribute of the Fakes element in this file to ‘true’ and rebuild the project.

Just shim or stub the things you really need, here is one of my example in real project:

1
2
3
4
5
6
7
8
9
10
11
12
13
<Fakes xmlns="http://schemas.microsoft.com/fakes/2011/" Diagnostic="true">
<Assembly Name="Microsoft.WindowsAzure.Configuration" Version="3.0.0.0"/>
<StubGeneration>
<Clear/>
</StubGeneration>
<ShimGeneration>
<Clear/>
<Add FullName="Microsoft.Azure.CloudConfigurationManager"/>
</ShimGeneration>
<Compilation>
<Property Name="PlatformTarget">x64</Property>
</Compilation>
</Fakes>

Other Options

  • Moq which is my favourite test framework

References:

And about markdown:

C# Unit Test with Microsoft Fakes (2024)

References

Top Articles
Latest Posts
Article information

Author: Lakeisha Bayer VM

Last Updated:

Views: 5928

Rating: 4.9 / 5 (69 voted)

Reviews: 84% of readers found this page helpful

Author information

Name: Lakeisha Bayer VM

Birthday: 1997-10-17

Address: Suite 835 34136 Adrian Mountains, Floydton, UT 81036

Phone: +3571527672278

Job: Manufacturing Agent

Hobby: Skimboarding, Photography, Roller skating, Knife making, Paintball, Embroidery, Gunsmithing

Introduction: My name is Lakeisha Bayer VM, I am a brainy, kind, enchanting, healthy, lovely, clean, witty person who loves writing and wants to share my knowledge and understanding with you.