What is Fakes:
Microsoft Fakes is
a testing framework which helps us to test code and introduce fake object for
external dependencies. This framework is
mostly useful in test driven development and also can be used in functional
driven development.
We can create
fakes using two ways
Stub is that part
of the code which gets executed instead of the actual code. When you run unit
test against a unit of code and the code consist of objects that are reference
by interfaces then we use stubs to create fake objects and execute that
functionality. Stub should not be used for classes they are strictly for
interfaces and abstract class.
Shims are another
type of fakes that execute methods and return values so that actual method that
is unit tested is not broken and testing is well under control.
Pre-requisites:
·
Visual Studio 2012 Premium or above
Shim
Example:
- Create new
project, then select “Unit Test Project” under Test Category
- Assume that you
have code as below in in your project
namespace HRMS
{
public class Employee
{// Business Layer
public Emp GetEmployeeDetails(int id)
{
DataLayer dlData = new DataLayer();
return dlData.GetEmployeeData(id);
}
}
public class Emp
{// Model
public int ID;
public string Name;
public String Location;
}
class DataLayer
{// Data Layer
internal Emp GetEmpData(int id)
{
return new Emp { Location = "HYD", Name = "Jhon" };
}
}
}
Now we will
test “GetEmployeeDetails”
method.
- Add
your testable project dll to unit test project. Here “HRMS.dll” will be
added to our “UnitTestWithFakes” project.
- Now
Right click on HRMS.dll and click on “Add Fakes Assembly”,
- After adding it will create HRMS.Fakes.dll and HRMS.Fakes files in
your project,
- Add using
statement of your fakes dll as using HRMS.Fakes;
- Now
create a test method as below in your test project,
[TestMethod]
public void GetEmployeeDetailsTest()
{
// Everything should be under
the context of Shim only by using shimsContext
using (ShimsContext.Create())
{
//Method to give the fake
data using delegates
ShimDataLayer.AllInstances.GetEmployeeDataInt32 = (instance, empid)
=>
{
return new Emp { Location = "Bangalore", Name = "Scott" };
};
Employee
employeeObj = new Employee();
Emp response =
employeeObj.GetEmployeeDetails(101);
Assert.AreSame("Scott",response.Name);
}
}
In the above
example we are calling “GetEmployeeDetails” in that it is internally calling “GetEmployeeData”, we shim
that method to replace the database call and provide dummy data.
While executing
when the process reach “GetEmployee”, it will come to our delegate and whatever
we pass from that it will take and return.
Now if you
observe the class name will be shimmed and we get all the methods in the
“AllInstances” of that class, by appending the parameters to the method, in the
above case “GetEmployeeData”
is the method and Parameter type is “Int32”. I.e. it is “GetEmployeeDataInt32”.
Parameters for
the delegate is MethodParametersCount+1.
For testing
purpose, I have tested with employee name.
Stub
Example:
- Prepare an
interface as below , in this case “IEmployee” is interface and method is “CheckEmployeeExist”
public interface IEmployee
{
bool CheckEmployeeExist(int EmpID);
}
- Implement
the interface, we can have multiple methods as well, I have taken one for
sample,
public class DataLayer : IEmployee
{// Data Layer
public bool CheckEmployeeExist(int id)
{// In real time we check with data
base here
return true;
}
}
- Unit
test method in test project,
[TestMethod()]
public void isEmployeeExist()
{
IEmployee iEmp = new HRMS.Fakes.StubIEmployee()
{
CheckEmployeeExistInt32 = (empid) =>
{
return false;
}//
Interface methods which are stubbed
};
bool response = iEmp.CheckEmployeeExist(101);
Assert.IsFalse(response); }
In the above the interface
having the methods, which are stubbed.
We can have multiple
methods with Comma (,) separation.
The base implementation of
the method returns “True”, but to check we return “false” in stub method.
Shim
Property:
You can shim the property
of a class like below,
string name = "TestProperty";
ShimEmp.AllInstances.NameGet = (stri) => { return name; };
The property must have get setter to make shim.
When
to Use What:
Use Shims
|
Use Stubs
|
To fake the class members
|
To fake the interface or abstract members
|
To refer external referenced assemblies
|
Within the solution calls
|
When performance is not required
|
When performance is required
|
When you have static,
non-virtual , sealed virtual methods
|
When you don’t have static,
non-virtual , sealed virtual
|
Not possible, when we don’t have testable methods
|
When we don’t have testable methods
|
It can fail while testing the code
|
It will never fail
|
No need of strong type
|
When we want strongly typed
|
To replace calls to .Net assemblies
|
Can’t be used for .Net assemblies
|
Note: To
create fakes, the dll must have property “Copy Local: True”.
Code Samples for Redis
Cache
For Redis Cache StringGet
()