Author: Haroon Khalil
-
Example 2: Observing the behavior of void methods
When a method returns an object, it is natural to think that assertions will check whether the returned object is as expected. However, this does not happen naturally in void methods. If your method does not return anything, what will you assert? It is even more complicated if what you need to assert stays within the method.…
-
Example 1: Introducing methods to facilitate assertions
Take another look at the processAll() method and its test, in listings 7.2 and 7.5. Most of what its test asserts is the interaction with the ports. Such assertions are easily done, and we did not need much more than basic Mockito. Now, let’s look closer at one specific assertion: verify(someCart).markAsReadyForDelivery(someDate);. The someCart instance of ShoppingCart is not a mock but a spy.…
-
Making your classes and methods observable
Observability, at the class level, is about how easy it is to assert that the behavior of the functionality went as expected. My main advice is to ensure that your classes provide developers with simple and easy ways to assert their state. Does a class produce a list of objects you need to assert one…
-
Dependency injection and controllability
At the architectural level, we saw that an important concern is to ensure that application (or domain) code is fully separated from the infrastructure code. At the class level, the most important recommendation I can give you is to ensure that classes are fully controllable (that is, you can easily control what the class under test does)…
-
Separating infrastructure code from domain code
I could spend pages discussing architectural patterns that enable testability. Instead, I will focus on what I consider the most important advice: separate infrastructure code from domain code. The domain is where the core of the system lies: that is, where all the business rules, logic, entities, services, and similar elements reside. Entities like Invoice and services such as ChristmasDiscount are examples…
-
Introduction
I usually say that every software system can be tested. However, some systems are more testable than others. Imagine that for a single test case, we need to set up three different web services, create five different files in different folders, and put the database in a specific state. After all that, we exercise the feature…
-
What do others say about mocking?
cAs I said, some developers favor mocking, and others do not. Software Engineering at Google, edited by Winters, Manshreck, and Wright (2020), has an entire dedicated to test doubles. Here’s what I understood from it, along with my own point of view:
-
Mocking types you do not own
Mocking frameworks are powerful. They even allow you to mock classes you do not own. For example, we could stub the LocalDate class if we wanted to. We can mock any classes from any library our software system uses. The question is, do we want to? When mocking, it is a best practice to avoid mocking types…
-
Date and time wrappers
Software systems often use date and time information. For example, you might need the current date to add a special discount to the customer’s shopping cart, or you might need the current time to start a batch processing job. To fully exercise some pieces of code, our tests need to provide different dates and times…
-
What to mock and what not to mock
Mocks and stubs are useful tools for simplifying the process of writing unit tests. However, mocking too much might also be a problem. A test that uses the real dependencies is more real than a test that uses doubles and, consequently, is more prone to find real bugs. Therefore, we do not want to mock a dependency…