I've been writing some new Hands On Labs for the WCF REST Starter Kit and as I mentioned previously on my blog I want to include unit tests. Several people commented on my previous efforts and pointed out that the tests I included with the REST Collection lab are really integration tests because they use the HTTP stack to pass messages from a client to the REST Service.
So this time I've decided to build out both an integration test layer and a unit test layer. My goal for the unit test layer was to exercise the service without the HTTP stack or the database. What this means is that I had to come up with a way to mock the database layer.
In my previous code I was using static methods on the CohoDB class backed up by LINQ to SQL classes. This time I took a new approach that uses the Table Gateway pattern with a twist. I wanted to use the Factory pattern with the gateway and provide a way to substitute the factory with a Mock factory that I could use when unit testing. Sound confusing? Here is the pattern.
First you need to define an interface for the TableGateway
public interface IWineGateway { WineData GetWine(int wineID); IEnumerable> GetWines(int startIndex, int pageSize); IEnumerable> GetAllWines(); WineData AppendWine(WineData wineData); WineData UpdateWine(int wineID, WineData wineData); WineData PutWine(int wineID, WineData wineData, out bool inserted); void DeleteWine(int wineID); }
Next you need an interface for the Factory
public interface IWineGatewayFactory { IWineGateway CreateWineGateway(); }
Now you need to implement your interfaces, the factory and the table gateway with classes. To make it simple to create the table gateway I use a static property that defines the factory that will be used (it defaults to the factory that creates the real class) and a static method to create the gateway.
public class WineGateway : IWineGateway { static IWineGatewayFactory _factory; public static IWineGatewayFactory Factory { get { // Default to the WineGatewayFactory if (_factory == null) { _factory = new WineGatewayFactory(); } return _factory; } set { // Unit tests can set a MockFactory if they like _factory = value; } } public static IWineGateway Create() { return Factory.CreateWineGateway(); }
Now when I need a table gateway I can call the static Create method and get one. However it still wasn't quite as convenient as I wanted so in the consuming service I added a property of type WineGateway that automatically created it when I needed it.
IWineGateway _winesGateway; IWineGateway WinesGateway { get { if (_winesGateway == null) _winesGateway = WineGateway.Create(); return _winesGateway; } }
This allows me to make calls into the table gateway with one simple line of code, just like I did before using the static methods on CohoDB
protected override WineData OnGetItem(string id) { Int32 wineID; if (!Int32.TryParse(id, out wineID)) { throw new WebProtocolException(HttpStatusCode.BadRequest); } return WinesGateway.GetWine(wineID); }
Beautiful isn't it? But wait there's more! What about when unit testing? No problem, just inject the Mock factory instead and create a class that implements the gateway interface
[TestInitialize()] public void MyTestInitialize() { // Setup the WineGateway to use the mocks WineGateway.Factory = new MockWineGatewayFactory(); }
Now my project has both integration and true unit tests. I haven't posted it on the web yet because I've more cleanup work to do and need to finish writing the docs but it's going to be great!
PingBack from http://www.codedstyle.com/mocking-the-tablegateway-pattern-2/
Factories are great when you have many implementations of the same interface, but when you just need to swap out a dependency for testing it seems like overkill, I prefer the following pattern.
<code>
public class WineGateway : IWineGateway
{
IRepository _repository;
public void WineGateway(IRepository repository)
_repository = repository;
}
public void WineGateway() : this(new DefaultRepository())
// Implementation...
// normal usage
var wineGateway = new WineGateway();
// test usage
var wineGateway = new WineGateway(new TestRepository());
// or alternatively using Moq
var wineGateway = new WineGateway(CreateMockRepository().Object);
</code>
I can use the same method to swap out any dependency that WineGateway uses that is not directly related to the unit test I am writing (for example I could also pass an ILog or an INotificationService in the constructor).
An added benefit is that it is only a small step to start using Dependency Injection container (IOC).
var wineGateway = container.Get<IWineGateway>();
Dude - that is brilliant. I'm going to use that method instead. It really simplifies things.