Unit tests and Builder Pattern— А match made in heaven

iamprovidence
3 min readSep 7, 2022

--

Nowadays, whenever somebody talking about unit tests, the first thing that comes to your mind will be Mock. And that not surprising. They sure do help. Mocks allow us to get rid of uncontrollable dependencies and replace them with predefine values. But removing dependencies is not the only thing you can do for your unit tests.

One of the most annoying thing with unit tests, that you need to support them all the time. It may be fun at the beginning, but when your code become shabby and rigid, the whole fun part goes away. Whenever I see red circle of failing test and big grumpy ̶t̶e̶s̶t̶ monster in front of me, I barely can stand a tempting feeling to just give up and remove everything. It seems like developers always forget that unit tests are as much important as code they write. And it is equally valuable to keep your tests clean and shiny.

There are some techniques to achieve that. Hope you will learn one by following our small tutorial.

Let’s imagine we are working on e-commercial project. In that domain, we have an aggregate that represents Order(for simplicity we will omit some details):

There is nothing special with that class. It looks like thousands of aggregates you have come across. It follows all DDD recommendation and what is more important it serves its purpose. Roger that.

Keep following. The GetTotal() method wasn't around yesterday. We have added it recently. The next logical step would be to cover it with test:

Ugh, yikes 😧 If I were you, I would not show that to my colleagues.

The most dirty part in unit test turned out to be Arrange section. That’s not surprising. After all, it is a place where all kitchen going. Even though tons of property are not needed for our unit tests to work, we are forced to initialize them. Looks clumsy, isn't it? Don’t worry, I here to help you.

The first thing you need to do is to implement builder for our aggregate.

It is a simple class that is hardly doing something. All it does is implement a couple of SetVelue() methods and call Order’s constructor with all gathered values at the very end. The key thing to notice that each method return this to allow fluent chaining of methods.

There is also no need to implement SetValue() methods for each property. Just add those you need now, and somebody else could extend it according to one needs (True lazy developer way 😎).

And now, let’s enhance that ugly Arrange section with our builder:

The Arrangesection is still big and code become more verbose. Is it actually bad? At least now you can tell what is going on and what those values mean.

Notice also how there is much less noise. We no longer need to write down each value, only those you need.

Somebody reorders parameters in the constructor. Don’t care.

Somebody adds an extra one. Don’t care. No need to update thousands of tests, just a single builder.

Ask yourself which version of test you would rather maintain and which likely be deleted. I think the answer is obvious.

Now, go into all the world and preach what you have behold to every creature 😁 Treat your unit test the same way you do with your code, and fun will return to your work. Tip me if you like it ☕️ And don’t forget to follow to receive more useful advices on software development 😉

--

--

iamprovidence

👨🏼‍💻 Full Stack Dev writing about software architecture, patterns and other programming stuff https://www.buymeacoffee.com/iamprovidence