In my previous post “Create test objects using Factory Methods or Object Mother pattern” I described how Factory Method and Object Mother patterns can be used to help with creating object instances. Presented solution allows to remove code duplication from unit tests making them easier to adopt changes in tested objects, but doesn’t help much with test code readability, which is very important factor in maintaining unit tests. Using sample
Address class from the previous article, imagine following code:
Address address = new Address("Poland", "Slask", "Zabrze", "Chrobry", "13", "46-230");
For someone who doesn’t know a lot about Poland’s geography and addressing system, it is really hard to recognise which parameter represents
County, City or Street, and when it comes to numbers the situation is even worse. To solve the mystery meaning of parameters, reader must go to class definition or use help from tools such as IntelliSense. Maybe it doesn’t seem like much effort, but it breaks the reading process and de-concentrates reader. It is like reading a book in foreign language with many new words. The reader spends more time going through the dictionary than reading a book and in effect doesn’t remember much from what she read. Soon, the reader stops checking every unknown word in the dictionary and starts to assume its meaning from the context, although in many cases the assumption is wrong (Some of the novels I read when I was learning English I read several times, and every time it was like reading different book). To help the reader with understanding the unit test, it must be written in a way that there is no need to leave the page or assume any meaning, but code is kept conscience and free from duplication.
Now, look at following example:
Address address = new AddressBuilder() .WithCountry("Poland") .WithCounty("Slask") .WithCity("Zabrze") .WithStreet("Chrobry") .WithHouseName("13") .WithPostCode("46-230") .Build();
This time, to create an instance of
Address we used
AddressBuilder which is an implementation of Builder pattern. We also used Method chaining technique which simplifies the code required to build an object. The above code is much easier to read and doesn’t require from reader the intensive knowledge of
Address object, making reading unit tests written by or colleagues a real pleasure.
Below is the
The two methods at the end:
InBrentfordUK make building sample addresses easier and can be used in tests, where the exact content is not as important as the fact that the addresses are different. The example can be a test of collection with addresses which doesn’t allow duplicated entries:
// addresses is a collection which doesn't allow duplicated entries addresses.Add(new AddressBuilder().InBrentfordUK().Build()); addresses.Add(new AddressBuilder().InGuildfordUK().Build());
By using descriptive names we are telling a reader that the former address is in Guildford in the United Kingdom, while the latter address is in Brentford, UK.