Sunday, November 29, 2015

Making the Setup phase of Unit testing easier with StructureMap and FakeItEasy

In this post I am going to show you how I am using StructureMap Registry along with FakeItEasy to make the setup phase of my unit tests easier. By no means I am claim that this is how it should be done but I feel it can be done this way. If you find any issues or it could be done better please let me know in the comments below. I will be happy to correct it and respond. In this post I am assuming you know about StructureMap, Dependency Injection, FakeItEasy and Unit Testing in general.

First about the problem I was facing and I am sure you must have faced it too and already solved it some other way. My system under test in this example is about an OrderingService which is responsible for placing orders, checking if inventory is there in warehouse or not and notify via email and log messages to database. Below is the code for OrderingService. We are not interested in the details for the PlaceOrder function here.

So you see in the setup method how much ceremony it requires to test this ordering service and if you have to do this again for another service then again all the dependencies have to be hooked in like this. Now for simplicity the paymentService and warehouseservice doesn’t take in any dependency so it is just a straight A.Fake<IPaymentService>(). This is all handy dandy for testing one service. But this isn’t ideal if you want to test another service which may require similar setup. And another thing I kept reading everywhere is writing unit tests should be fast and easy and the setup should feel just like how you wrote your system under test. Clearly the setup phase is way different from how we wrote the OrderingService above. You may ask how it is different? In the constructor of OrderingService, do you have to worry where LoggingService is getting its IDataManager from or EmailService getting its ISmtpServer? No right. Because it is being taken care by StructureMap registry like below.

So you may ask why are you writing your setup that way. One reason is that I didn’t knew any other way and I learnt stuff harder way using google. For now lets focus on a light bulb moment that inspired me to make my code better. And here is a better way according to me. Just like how StructureMap took care for me the registration of all dependencies [I love you StructureMap] of OrderingService why not StructureMap take of registering all the Fake dependencies [light blub]. Let’s create a different Registry which we will call FakeStructureMapRegistry.cs

Question: Why I am also registering SUT OrderingService inside FakeStructureMapRegistry? Because in this Fake registry I don’t want to keep changing which class is under test and which one isn’t. I will register all the Fakes at once and not worry about it. More on that in the next paragraph. Now we will use this Fake registry in our setup method. So here is how my modified unit test looks like.

Let’s go into detail about the first three lines in the Setup method and rest is self explanatory. Line 1 – we create a new structuremap container and add our FakeStructureMapRegistry class. That takes care of configuring all the Fake dependencies including our SUT which should never be a mocked or faked object. Hence line 2 – which tell the container to eject all the instances of IOrderingService because I will configure it as not Fake and real OrderingService on Line 3. So that’s all. The rest of the lines gets instances from the container which will look a bit familiar to the constructor of OrderingService. I love this setup method. This exactly feels how I would write my system under test. If you were to configure another service say LoggingService then it would be like this.