Throughout this book, we have been testing systems that we have been developing to solve our problem domain; hence, they are under our total control. Whenever our system tried to use another one that is not under our control, or simply involves another problem domain, we have used test doubles to replace them in our tests. This is a good practice, since we avoid composing scenarios and features from different systems, and because we can set up such test doubles to perform predictable tests. The trick here is to configure the test doubles to make them behave in a way that simulates the behavior of the other system in a realistic way. This always leads to the same doubt: are our test doubles good enough?
Of course, we will eventually need to write code that implements the interfaces that we have been mocking. This gives us two possibilities, which are explained here:
We need to write a fair amount of nontrivial code to implement those interfaces. In this case, we can...