Archive

Archive for April, 2012

Fakes Framework in Visual Studio 11

April 8, 2012 1 comment

Microsoft has introduced the Fakes Framework in Visual Studio 11, which is the replacement for both private accessors and the original Moles framework.

For those that are unfamiliar with Moles, it was an isolation framework that allowed us to replace dependencies in our unit tests. For example, if our legacy code uses the static method Util.GetUser() to retrieve information from a database, there isn’t an easy way to change or remove that behavior. Moles allowed us to intercept the call to Util.GetUser() and redirect it to our own implementation. This is important because we want to keep our unit tests isolated, free from external dependencies such as the database. Keeping the results deterministic is also a good way to ensure that our test results are consistent.

The Fakes Framework introduces two types of fakes: stubs and shims. Stubs allow us to replace a method with our own implementation for interfaces and virtual methods. Shims allow us to override methods that usually can’t be overridden, such as static methods and non-virtual methods. Shims also allow us to intercept calls to types found in the .NET base class library.

public class AuthenticationService
{
    private readonly IUserRepository repository;

    public AuthenticationService(IUserRepository repository)
    {
        this.repository = repository;
    }

    public bool Authenticate(string username, string password)
    {
        User user = repository.GetUser(username);
        return user.Password == password;
    }
}

For our test, we want to make sure that Authenticate() returns false when the password does not match what’s returned from the repository. The AuthenticationService requires an instance of IUserRepository. We can use a stub to replace the method call GetUser().

The Fakes Framework will generate strongly typed fakes for each assembly that we want to fake. For stubs, each type will be prefixed with Stub. In the test below, we’ll be using the stub StubIUserRepository, which is an implementation of the interface IUserRepository. Each method/property on the stubbed type will contain delegates that are named very similar to the original method/property. We can change the implementation of the method GetUser() by assigning a delegate to the GetUserString field on the stubbed type.

[TestMethod]
public void Demo()
{
    var repository = new StubIUserRepository();

    repository.GetUserString = 
        username => new User { Name = "Malvin", Password = "secret" };

    var service = new AuthenticationService(repository);
    var isAuthenticated = service.Authenticate("Malvin", "password");

    Assert.IsFalse(isAuthenticated);
}

When GetUser() is called from AuthenticationService, the repository will return our hard-coded User with the name “Malvin” and password “secret”.

However, there are cases when it isn’t possible to replace the repository:

public class AuthenticationService
{
    public bool Authenticate(string username, string password)
    {
        UserRepository repository = new UserRepository();

        User user = repository.GetUser(username);

        return user.Password == password;
    }
}

Let’s assume that we want to run the same test again. Instead of using stubs, we’ll use a shim to intercept the call to GetUser().

The Fakes Framework will generate strongly typed shims for each type in the original assembly. Each type are prefixed with Shim. Before we can use shims, we must create a new context under which the shims will be active.

In our test, we are specifying that for all calls to GetUser() for any instance of UserRepository while inside the ShimContext, we want to intercept that call and return our own User.

[TestMethod]
public void Demo()
{
    using (ShimsContext.Create())
    {
        ShimUserRepository.AllInstances.GetUserString =
            (repository, username) => new User { Name = "Malvin", Password = "secret" };

        var service = new AuthenticationService();
        var isAuthenticated = service.Authenticate("Malvin", "password");

        Assert.IsFalse(isAuthenticated);    
    }
}

For cases where we may not want to override the behavior for all instances of a type, we can create individual instances:

var repository = new ShimUserRepository();
repository.GetUserString = username => new User();

We can also replace static methods with our own implemention.

public static class Util
{
    public static User GetUser(string username)
    {
        // ...
    }
}

The shim:

ShimUtil.GetUserString = username => new User();

Shims also allow us to override the behavior of base classes. Here we have a CachedUserRepository, which caches any users returned from UserRepository. If a user is found in the cache, the cached user will be returned. If a user is not found in the cache, we will use the base class to retrieve the user and add it to the cache.

public class CachedUserRepository : UserRepository
{
    private static List<User> cache = new List<User>();

    public new User GetUser(string username)
    {
        User cachedUser = cache.FirstOrDefault(x => x.Name == username);
            
        if (cachedUser != null)
            return cachedUser;

        User user = base.GetUser(username);

        if (user != null)
            cache.Add(user);

        return user;
    }
}

Using shims, we can replace the the base method base.GetUser(). By creating a shim for the base class and passing the inheriting class to the shim’s constructor, we can override the base class’s behavior.

[TestMethod]
public void Demo()
{
    using (ShimsContext.Create())
    {
        var cachedRepo = new CachedUserRepository();
        var baseClass = new ShimUserRepository(cachedRepo);

        baseClass.GetUserString = 
            username => new User { Name = "Malvin", Password = "password" };

        var user = cachedRepo.GetUser("x");

        Assert.AreEqual("Malvin", user.Name);
    }
}

The new Fakes Framework is definitely a great tool for testing legacy code, but I would be hesitant to use it for anything else. Most existing mocking frameworks have a much cleaner API. Refactoring can be difficult since the framework generates strongly typed stubs and shims for an assembly. Renaming methods or classes in the original assembly will cause your tests to fail. I would also suggest that if you’re using shims extensively in a new project, there’s probably something wrong with your design.

Executing code in a new application domain

April 8, 2012 9 comments

A coworker recently mentioned a scenario where he needs to use legacy code in a multi-threaded environment. The class in-question is written in such a way that it holds state and needs to be reset before the class itself can be used again, therefore preventing it from being used in multiple threads at the same time. Although it may not be the most efficient method, we can create a new application domain for each thread and execute the code in there.

Just prototyping out some ideas, an API like this may be useful:

NewAppDomain.Execute(() =>
{
	// Run code in here
});

Each call to Execute would create a new application domain.

AppDomain domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

To execute our Action that we’re passing to the Execute method, we’ll need to create a new instance of Action in our new application domain. However, trying to call the CreateInstanceAndUnwrap method on the new application domain will throw an exception:

Unhandled Exception: System.MissingMethodException: Constructor on type 'System.Action' not found.

Instead, we’ll need to create a new class that can be instantiated in the new application domain. This new class AppDomainDelegate will act as a delgate and execute the Action that we pass to it.

public static class NewAppDomain
{
    public static void Execute(Action action)
    {
        AppDomain domain = null;

        try
        {
            domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

            var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
                typeof(AppDomainDelegate).Assembly.FullName,
                typeof(AppDomainDelegate).FullName);

            domainDelegate.Execute(action);
        }
        finally
        {
            if (domain != null)
                AppDomain.Unload(domain);
        }
    }

    private class AppDomainDelegate : MarshalByRefObject
    {
        public void Execute(Action action)
        {
            action();
        }
    }
}

Now we can use this class to execute code in another application domain.

NewAppDomain.Execute(() =>
{
    Console.WriteLine("Hello World");
});

Parameters

Trying to use variables declared outside the scope of the lambda will throw a serialization exception.

int i = 0;

NewAppDomain.Execute(() =>
{
	Console.WriteLine("Hello World " + i);
});

We can update the code to receive parameters across application domains by adding an overload for the Execute method:

public static class NewAppDomain
{
    public static void Execute(Action action) { ... }

    public static void Execute<T>(T parameter, Action<T> action)
    {
        AppDomain domain = null;

        try
        {
            domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

            var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
                typeof(AppDomainDelegate).Assembly.FullName,
                typeof(AppDomainDelegate).FullName);

            domainDelegate.Execute(parameter, action);
        }
        finally
        {
            if (domain != null)
                AppDomain.Unload(domain);
        }
    }

    private class AppDomainDelegate : MarshalByRefObject
    {
        public void Execute(Action action) { ... }

        public void Execute<T>(T parameter, Action<T> action)
        {
            action(parameter);
        }
    }
}

Now we can pass parameters to the method. We’ll need to make sure that any parameters we pass are marked as Serializable since they will be serialized and deserialized across application domains.

int i = 0;

NewAppDomain.Execute(i, x =>
{
    Console.WriteLine("Hello World " + x);
});

Returning Results

In cases where we want the Execute method to return results, we can add two additional method overloads that use Func<T> instead of Action:

public static T Execute<T>(Func<T> action)
{
    AppDomain domain = null;

    try
    {
        domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

        var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
            typeof(AppDomainDelegate).Assembly.FullName,
            typeof(AppDomainDelegate).FullName);

        return domainDelegate.Execute(action);
    }
    finally
    {
        if (domain != null)
            AppDomain.Unload(domain);
    }
}

public static TResult Execute<T, TResult>(T parameter, Func<T, TResult> action)
{
    AppDomain domain = null;

    try
    {
        domain = AppDomain.CreateDomain("New App Domain: " + Guid.NewGuid());

        var domainDelegate = (AppDomainDelegate)domain.CreateInstanceAndUnwrap(
            typeof(AppDomainDelegate).Assembly.FullName,
            typeof(AppDomainDelegate).FullName);

        return domainDelegate.Execute(parameter, action);
    }
    finally
    {
        if (domain != null)
            AppDomain.Unload(domain);
    }
}

… and the same overloads for the delegate class AppDomainDelegate:

public T Execute<T>(Func<T> action)
{
    return action();
}

public TResult Execute<T, TResult>(T parameter, Func<T, TResult> action)
{
    return action(parameter);
}

We can now get results back. We’ll need to make sure that any results we return are marked as Serializable.

Result first = NewAppDomain.Execute(() => new Result());
Result second = NewAppDomain.Execute(parameter, x => new Result());

Using The Class

The entire class can be found here. To demonstrate, we’ll create a class that uses a public static field as a counter.

public class SharedClass : MarshalByRefObject
{
    public static int Counter = 1;

    public void Print()
    {
        Console.WriteLine(AppDomain.CurrentDomain.FriendlyName + " - " + Counter);
        Counter++;
    }
}

We’ll call the Print method in another application domain using our NewAppDomain class:

NewAppDomain.Execute(() =>
{
	new SharedClass().Print();
	new SharedClass().Print();
});

NewAppDomain.Execute(() =>
{
	new SharedClass().Print();
	new SharedClass().Print();
	new SharedClass().Print();
	new SharedClass().Print();
});

The result:

New App Domain: 3ca2e6de-a5bd-40ef-b471-edb8c19024c2 - 1
New App Domain: 3ca2e6de-a5bd-40ef-b471-edb8c19024c2 - 2
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 1
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 2
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 3
New App Domain: 2037d461-79fe-48c1-abf1-2c58bb6b02cf - 4

If the application domain was the same, we would have seen the counter increment to 6. Notice that SharedClass inherits from MarshalByRefObject. If we instantiate a new instance of SharedClass and pass it as a parameter to our Execute method, this object is now shared across application domains via remoting. To demonstrate, we can use the Execute overload that takes a parameter:

var sharedClass = new SharedClass();

sharedClass.Print();
sharedClass.Print();

NewAppDomain.Execute(sharedClass, x => x.Print());

sharedClass.Print();

The result:

AppDomainDemo.exe - 1
AppDomainDemo.exe - 2
AppDomainDemo.exe - 3
AppDomainDemo.exe - 4

As expected, the counter did not reset. However, if we change SharedClass by removing MarshalByRefObject and marking the class as Serializable, we’ll see a different result:

AppDomainDemo.exe - 1
AppDomainDemo.exe - 2
New App Domain: b9404ee9-f4fc-4937-84ad-9d0369e36bb6 - 1
AppDomainDemo.exe - 3