Microsoft Fakes isolation framework
If you want to isolate the code which you want to create tests from the the code which you don’t Microsoft fake is the solution. By isolation the code being tested make your life easier when identifying where the error is causing when a unit test fails.
Types of “Fakes”
Stub :-
Lets see how to use shim & stub for unit test code isolation.
Here we have defined an interface names IStubSample which will be used in the StubSample class.
public bool ValidateInvoicePrice(IStubSample sample)
{
int price= sample.GetInvoicePrice();
if (price > 0)
{
return true;
}
else
{
return false;
}
}
[TestMethod]
public void TestContosoStockPrice()
{
// Arrange:
// Create the fake stockFeed:
IStubSample stubFeed =
new VS2012UnitTest.Fakes.IStubSample() // Generated by Fakes.
{
// Define each method:
// Name is original name + parameter types:
GetInvoicePrice = () => { return 1200; }
};
// In the completed application, stockFeed would be a real one:
var componentUnderTest = new StubSample();
// Act:
bool actualValue = ValidateInvoicePrice.GetContosoPrice(stubFeed);
// Assert:
Assert.AreEqual(true, actualValue);
}
Hope this gives you idea on fundamentals of fakes in Microsoft unit testing. We’ll discuss on this more details in the future posts.
Happy Fake :)
Types of “Fakes”
Stub :-
Shim :-Replaces another class with a small substitute that implements the same interface. To use stubs, you have to design your application so that each component depends only on interfaces, and not on other components. (By "component" we mean a class or group of classes that are designed and updated together and typically contained in an assembly.)
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 can be used to replace calls to assemblies that you cannot modify, such .NET assemblies.
When To Use
As a general practice it is recommended to use Stubs for the calls with in your visual studio projects & shims for the referenced Dlls such as system Dll’s. If you have to use shims to isolate the tests which uses the classes with in your projects indicates that your code is badly designed which has not decoupled. We have use shims when we use methods in system Dll’s as they don’t provide interface definitions to override.
Shim | Stub | |
Performance | Slow | High |
Static methods, sealed types | Supports | only supports to implement interfaces |
Internal types | Supports | Supports |
Private methods | can replace calls to private methods if all the types on the method signature are visible | only replace visible methods |
Interfaces and abstract methods | Do not Support | Supports |
Using Shims
1. Create a class Library & add a Class which contains System.DateTime
public class ShimSample
{
public bool UpdateInvoice()
{
bool invoiceUpdated = false;
if (DateTime.Today.Month== 1)
{
invoiceUpdated = true;
}
return invoiceUpdated;
}
2. Add new Unit Test Project to your solution & add a test method to test the above method.
3. As System.DateTime is available in System.dll we need to the fake assembly of it to the test project. (note :- this facility is only available in VS2012 Ultimate)
- Right click on the System under references & click on “Add Fake Assembly”. That’ll add Fake system reference to your test project.
- Add Shim code inside Shim context. It is required to create Shim context when we use Shims inside our test code to define the lifetime of the shim content.. If we didn’t require this, your shims would last until the AppDomain shut down.
[TestClass]
public class TestShimSample
{
[TestMethod]
public void UpdateInvoice()
{
// Shims can be used only in a ShimsContext:
using (ShimsContext.Create())
{
// Arrange:
// Shim DateTime.Now to return a fixed date:
System.Fakes.ShimDateTime.NowGet =
() =>
{ return new DateTime(2012, 1, 1); };
// Instantiate the component under test:
var componentUnderTest = new ShimSample();
// Act:
bool result = componentUnderTest.UpdateInvoice();
// Assert:
// This will always be true if the component is working:
Assert.AreEqual(true, result);
}
}
}
Using Stubs
1. First Inject the Interface
In order to use stubs in your tests you have to design your code using dependency injection.. Variables and parameters should be declared by using interfaces and instances of other components should be passed in or created by using a factory.Here we have defined an interface names IStubSample which will be used in the StubSample class.
public bool ValidateInvoicePrice(IStubSample sample)
{
int price= sample.GetInvoicePrice();
if (price > 0)
{
return true;
}
else
{
return false;
}
}
2. Add the fake Assembly
Add the reference of your project to the test project. Then add the fake assembly of the assembly which contains the interface of that in to the test project. Then create the test as follows.[TestMethod]
public void TestContosoStockPrice()
{
// Arrange:
// Create the fake stockFeed:
IStubSample stubFeed =
new VS2012UnitTest.Fakes.IStubSample() // Generated by Fakes.
{
// Define each method:
// Name is original name + parameter types:
GetInvoicePrice = () => { return 1200; }
};
// In the completed application, stockFeed would be a real one:
var componentUnderTest = new StubSample();
// Act:
bool actualValue = ValidateInvoicePrice.GetContosoPrice(stubFeed);
// Assert:
Assert.AreEqual(true, actualValue);
}
Hope this gives you idea on fundamentals of fakes in Microsoft unit testing. We’ll discuss on this more details in the future posts.
Happy Fake :)
Comments
Post a Comment