Tags

Other

Why Building Units for Test Using Fluent Syntax is Worth the Time?

Recently I found myself working on a system that was written entirely in a TDD manner. Code coverage was amazing, but I needed to make changes. I was adding some classes and went about it with all the right intentions, all TDD. So I started to write tests for my first class. Set up the system under test (my as yet unwritten new class) with all its dependencies injected through the constructor as mocked out interfaces.

All was well, I continued to flesh out the requirements of the class as unit tests. They all failed. Then I added code and made all the tests pass with the mocked dependencies. At this stage I had a fully functioning class that did everything I needed it to do and the code was beautifully covered by a host of unit tests.

Digital Recruitment - Ronald James Group

Then came phase 2 of the project and with it the need for the class to do something more. While the open-closed principle would suggest we don't change the class, but maybe derive from it, add the new functionality to the derived type and only add the new dependencies to this derived type. I didn't do this. Rushing in headlong, I decided to crack open the stable, functional, fully tested and robust class.

This meant writing a number of new unit tests to prove the new functionality. The class needed to interact with a further dependency, and this meant extending the constructor to take an extra parameter.

Again I could have extended by adding a new constructor, leaving the old one but again that's not what I did. I changed the constructor and instantly broke every existing unit test. Actually, I didn't stop them passing, I stopped them compiling. This meant going through and adding the new dependency to every unit test. Very time-consuming.

At this point, I was reminded of a pattern I had used in the past. The one I should have used from the outset, but it would have taken an extra ten minutes at the start of development, which I chose not to do. So now I was left with something that would take over an hour to fix but saved me ten minutes a couple of weeks ago! Technical debt if I've ever seen it.

So to the pattern, fluent builders. The idea is rather than creating the class you want to test, you create on an object that will build it for you, the builder. Then you tell the builder what dependencies you want to inject into your system under test and ask it to build it. The fluent aspect comes from the way you do this. Imagine how you would phrase it. "I want a cup of coffee, with milk and with two sugars.  Or in code

Digital Recruitment - Ronald James Group

Backed by a class

public class CupOfCoffeeBuilder
{
public bool Milk{ get; set;}
public int Sugars{ get; set;}
CupOfCoffeeBuilder ()
{
// initialise any default values here
}
public CupOfCoffeeBuilder WithMilk(bool choice)
{
_milk = choice;
return this;

}
public CupOfCoffeeBuilder WithSugars(int howMany)
{
_sugars = howMany;
return this;
}
public CupOfCoffee Make ()
{
return new CupOfCoffee(_milk, _sugars);
}
}

This all means that when creating the cup of coffee, I only made it when we know all of the optional parts that go into it, the sugar and milk. In other words, we could make a cup of coffee with any combination of milk and sugar but we only have one make method, and that means only one call to the cup of coffee constructor.

This means for my case if I had used a fluent builder, adding the extra dependency would have meant adding one property, one method and one parameter to the single constructor call within my builder.

Digital Recruitment - Ronald James Group

The other advantage of this approach is that your tests become instantly more readable. And who can argue with code that is easier to read and easier to maintain?

Thanks to Mike Wardle for being our guest writer this week.

Who Are Ronald James?

We are a leading niche digital & tech recruitment specialist for the North East of England. We Specialise in the acquisition of high-performing technology talent across a variety of IT sectors including Digital & Technology Software Development.

Our ultimate goal is to make a positive impact on every client and candidate we serve - from the initial call and introduction, right up to the final delivery, we want our clients and candidates to feel they have had a beneficial and productive experience.

Contact our Team

If you’re looking to start your journey in sourcing talent or find your dream job, you’ll need a passionate, motivated team of experts to guide you. Check out our Jobs page for open vacancies. If interested, contact us or call 0191 620 0123 for a quick chat with our team.

Let's be Friends!

Follow us on our blog, FacebookLinkedInTwitter or Instagram to follow industry news, events, success stories and new blogs releases.

 

Back to Blog

</Follow Us>