I feel like I cheated a bit with this tool by using a rhyme that makes it both an asset but also a weapon or weak spot. Judge for yourself:
“Mocks, stubs and fakes are all tools we can use To ease our complexity and dependencies loose But check all the contracts on which you depend Don´t assume it´s working, leave no loose-end“
So, what does it mean?
First of all: I _love_ the idea of mocking out all dependencies. Isolation of concern, speed, ease of debugging – all the best things possible! I see why we want to have small small items with a single/few purposes that can be streamlined, re-used and easily replaced.
But: It does not make the _total_ less complex. It just makes the _parts_ less complex and the possibilities for failures between parts endless.
And: Communication is incredibly hard. Please remember that.
So, back to the card. When we have interfaces between services, systems, applications, apps etc: you have to make sure to test that interface. You have to make sure you agree on every in and out of that interface. And you have to make sure you test the ecosystem with AND without all parts.
Contract testing is an incredibly fun, but also complex, part of testing and it is easy to miss scenarios but just as easy to over-complicate things!
Parts can, and should, be tested with all dependencies removed – making sure we test that our small part(s) can handle both wanted and unwanted, expected and unexpected, responses. Other parts should, or can only, be tested with a single/some dependencies – making sure the contract we agreed on (please make sure you agree on one!) is upheld and that we handle it. And the most common, and/or most critical, error scenarios. But some things can only be tested in the complete ecosystem. What happens to _my_ service(a) if a second service(b) that a third service(c) relies on goes down?
Say My service “Add Customer” calls the “Check Address”-api to get the current address. “Check Address” calls a third service, “Preferred Line of Contact”. If that is down, how will the response back to me look? If “Preferred Line of Contact” suddenly adds a channel and “Check Address” can’t handle that, can my service handle that?
At more than one point in time during my career, teams have forgotten to update each other on changes to the set of data they accept/don’t accept, expect/don’t expect.
It can be as small as changing from true/false to 1/0, which a lot of times would be interpreted as the same thing – but not always. If you don’t know the tech stack on the other side very well – don’t expect it to work.
Other times they added/removed a certain value and thought it would work ok but as time passed, small changes grew and contracts stopped being relevant.
And then we have a few times when one side changed the contract completely and forgot to tell the people sending and/or receiving data. Of course, resulting in chaos and mayhem.
Communication is hard!
Quote of the day
“…One option is a lot faster than the other, has no dependencies and gets me fairly near the answers I want but omits lower level detail (windspeed, gradient) of the journey that I would learn by timing the walk myself. This is exactly what contract testing does. It mocks or interrogates a response to allow you to get some of the information about functions you require”