Friday, 14 June 2013

Mocking OS X with Mono and Moq

A quick way to test units of code with dependencies on other objects is to mock them up. This is not a new concept and the internet is awash with decent mocking frameworks and documentation on how to use them but I thought I'd jot a quick example anyway on how to go about mocking with mono on OS X.

I've built a simple class that has a dependency manually injected into its constructor.

Here is the interface for the dependency:

public interface IRepository
{
string Test();
}
view raw gistfile1.cs hosted with ❤ by GitHub

Implement the interface:

public class MyRepository : IRepository
{
public string Test()
{
return "Test";
}
}
view raw gistfile1.cs hosted with ❤ by GitHub


Create a class that depends on the IRepository:
public class MyWorkFactory
{
private IRepository _repository;
public MyWorkFactory(IRepository repository)
{
_repository = repository;
}
public string TestMe()
{
return _repository.Test();
}
}
view raw gistfile1.cs hosted with ❤ by GitHub
Now when we invoke the above class:
MyWorkFactory myFactory = new MyWorkFactory(new MyRepository());
Console.WriteLine(myFactory.TestMe()); // This should return "Test"
view raw gistfile1.cs hosted with ❤ by GitHub

All works as intended, the output is "Test" which is how we implemented the IRepository.

But when testing we want to isolate the MyWorkFactory class without having to rely on the working implementation of the IRepository interface.

So there are a few ways of going about this. We could create a new implementation of IRepository with known outcomes for testing. Or we can mock the dependency up.

I'm using Moq in this example as it's lightweight, works well on mono and is easy to use.

So let's mock/moq up the repository, inject it into the MyWorkFactory class and see what happens:

// mock up the interface
var mock = new Mock<IRepository>();
mock.Setup(f => f.Test()).Returns("My Mock");
// Pass in the mocked repository
MyWorkFactory myFactoryWithMoq = new MyWorkFactory(mock.Object);
Console.WriteLine(myFactoryWithMoq.TestMe()); // This should return "My Mock"
view raw gistfile1.cs hosted with ❤ by GitHub
So as can be seen, the MyWorkFactory object now uses our Mocked repository dependency and outputs "My Mock" so we can test the class in isolation and configure the dependencies to test all avenues.