Testing TFS functionality with Microsoft Fakes

For the past few months I’ve been working with a group of seriously smart people as part of my first ALM Rangers project.  This project was a “Quick Response” initiative to provide a Command-line utility and Visual Studio Extension to create TFS Branch scenarios.  The project was in response to the need to implement a consistent branching model as part of team project or team creation process, that complies with the VS TFS Branching and Merging Guide.  You can download the code from CodePlex: http://vsarguidance.codeplex.com/releases/view/96222 which also includes a Quick Reference Sheet.

We had an interesting challenge during this project, which was to be able to test our functionality without the need to call TFS from our Unit Tests.  After all, we were not testing whether TFS worked (there’s a whole bunch of people at Microsoft that take care of that), we just needed to make sure that the tool functioned properly.  Using a mocking framework was the logical choice here and it was the perfect opportunity to take a look the new Fakes framework.  From MSDN: “Microsoft Fakes help you isolate the code you are testing by replacing other parts of the application with stubs or shims. These are small pieces of code that are under the control of your tests. By isolating your code for testing, you know that if the test fails, the cause is there and not somewhere else. Stubs and shims also let you test your code even if other parts of your application are not working yet.”

Following are a few sample snippets of how Fakes was used.

The constructor of our SourceControlWrapper class looks like this:

public SourceControlWrapper(string teamProjectCollectionUrl, string teamProjectName)
{
    this.tpcollection = new TfsTeamProjectCollection(new Uri(teamProjectCollectionUrl));
    this.teamProjectName = teamProjectName;
    this.vcserver = this.tpcollection.GetService();
}

That gave us two opportunities to use the power of Fakes.  The first, to instantiate our TFS Team Project Collection, and the second one to get the Version Control service to perform version control operations.

The Shim for the Team Project Collection looks like this:

ShimTfsTeamProjectCollection.ConstructorUri = (@this, value) =>
{
    new ShimTfsTeamProjectCollection(@this) { NameGet = () => collectionUrl };
    new ShimTfsConnection(@this)
    {
        EnsureAuthenticated = () => { },
        CredentialsGet = () => new System.Net.NetworkCredential("testUser", "pwd", "testDomain")
    };
};

This forces all new instantiations of TfsTeamProjectCollection to use ShimTfsTeamProjectCollection and since TfsTeamProjectCollection inherits from TfsConnection I’m also intercepting calls to EnsureAuthenticated() method and the Credentials property.

The VersionControlserver part was a bit trickier, and it was resolved this way:

var versionControlServer = new ShimVersionControlServer
{
    CreateWorkspaceStringStringStringWorkingFolderArray = (a, b, c, d) => workspace,
    QueryWorkspacesStringStringString = (a, b, c) => new Workspace[0],
    GetTeamProjectString = a => teamProject,
    QueryBranchObjectsItemIdentifierRecursionType = (a, b) => new BranchObject[0],
    SupportedFeaturesGet = () => 8,
    ServerItemExistsStringItemType = (x, y) => true
};

ShimTfsConnection.AllInstances.GetServiceOf1(t => versionControlServer);

Reading from the bottom up, when GetService is called, it will return a ShimVersionControlServer that has the following shimmed methods & property:

public Workspace CreateWorkspace(string name, string owner, string comment, WorkingFolder[] mappings);
public Workspace[] QueryWorkspaces(string workspaceName, string workspaceOwner, string computer);
public TeamProject GetTeamProject(string name);
public BranchObject[] QueryBranchObjects(ItemIdentifier rootItem, RecursionType recursion);
public int SupportedFeatures { get; }
public bool ServerItemExists(string path, ItemType itemType);

There’s functionality throughout the command line tool that calls those TFS methods and also some workspace-related functionality.  So head over to CodePlex and download the code, get an awesome new tool and take a look at some Fakes code as a bonus!

Scroll to Top