Stop mocking your system!

Yes, mocking has a mostly negative meaning! Only this – to imitate (someone or something) closely – doesn’t feel negative.

Mocking is usually used in testing code and it looks something like this:
We have module A which uses modules B and C. When we write tests for module A, we don’t initialise it with the real B and C, but rather “mock” B and C and hand those mocks to A.

All of us have used mocks in our testing code, to substitute the real things. I know I’m definitely guilty of this. Why though? Why do we do it? Well, It’s usually because initialising those collaborators is not trivial (i.e. can’t be done with a one-liner).
But why wouldn’t the collaborators be easy to spin-up? Well, because they have their own issues with their own collaborators and so, you see, the design issues start to emerge. This is why you read things like “TDD makes your design” better (I’m not going to start this now… maybe in a future article).

But let’s backtrack a little bit and be honest with ourselves. What we’re actually doing is faking (please don’t start with the stub/fake flamewar) things that we’ve created ourselves. We lie to ourselves saying that we’re only testing one thing at a time, so having two or more real things breaks best practices. Which best practices? Stack overflow’s most voted answers? Check this out: you set your test victim with mocks and boom, now you have two of the same collaborators living in your codebase. And guess what… you have to keep the mocks in sync with the real things, in case you thought otherwise. Don’t worry, you’ll forget to do that once in a while (I’m being gentle here…) and you know what the end result of that is? Yes, yes, the all too familiar “green tests broken product” syndrome. You know… a dev and a QA walk in to a bar. QA says: “it doesn’t work”. Dev says: “it must be working, all the tests pass”. All the dev tests that is…
And this is exactly where the heart of the problem lies! Creating mocks is just creating an alternative universe for your system, that will eventually lose all connections with reality.
What you almost always want, when mocking, is really just different input data for your module, data normally provided by a long stream of collaborators. Just build your program in such a way that you can send it this data, regardless of the runtime (unit test framework, test env or production env). Yes, it is possible and highly desirable and don’t be in denial right now.

But dude, I don’t want to use a real database (or AWS endpoint or rocket launcher) in my tests. Debatable, but fair enough. Simulating 3rd party systems is acceptable when not doing so would lead to bad consequences in a production environment. Key concepts here are “3rd party” and “production”. If using a 3rd party production system won’t hurt anyone, just do it. Being as close to reality as possible is the best thing to do. Anything else is just a web of lies that we have to maintain.

Mocking your own system is just mocking your own reality. Stop lying to yourself!