Mocking is a very opinionated thing. Usually it considered as something bad, bad by itself, and as a reflection of a bad system design.
Someone said – don’t ever use mocks(stubs) in unit tests. Someone said – people struggle with all of the mocking required to isolate units, better use pure functions and observe side-effects. How? Go learn Inversion of Control, Dependency Injection and a better system design.
There is not such thing as a good system design, yet, but there is a obvious things which would lead to a bad system design.
Obvious? I could name an obvious thing to look for. As one said – hard to mock code is hard to use code, and I would say – mocking is a Base Layer of a well designed application, it is a cornerstone.
Here I should more clearly define what is mocking:
term “Mock Object,” which is where we “replace domain code with dummy implementations that both emulate real functionality and enforce assertions about the behavior of our code”
And, to be more concrete – mock is not a stub(hello sinon) or spy(hello Jest) – mock is a dependency mock. A replacement for a domain code.
Hereby I should explain what’s does mean domain code. To be more concrete – what should mean “domain” code here –
something bigger than a function, something smaller than everything. A Thing. A Block. A Part. Something you can name.
Like a module, a file system, a dependency, an API.
Something you might want to mock. And by mocking here I don’t mean “replace by a dummy implementation” – that’s quite a dummy ideal – “replace by something you need instead”.
Mocking is about replacing one part by another part. About choosing the right part.
Mocking is not about testing, it’s about changing constants. Reconfiguring a rigid body. Mocking will take you hard coded monolith with explicit dependencies between domains… and do whatever you have to do.
Once you can extract some functionality to a separate module – you shall do it. Once you can statically import your dependency- you shall do it. Once you are have to think, to use conditional require – you shall be… doomed.
Dependency injection and flexible configuration? Your code is shit! Your code is soft as shit. Wanna make it sharp as brilliant? Then make it static and hard as a brilliant!
Example? What about requiring different modules for nodejs and the browser?
This is a common issue for any “isomorphic “ application, or for any library, which could be used in both environments – you “require” something like PostgressConnector(conditionally) and your bundle size got bigger by 10 megabytes. Webpack is just doing what it was built for – bundling everything you may require.
There is same problem with distinguishing production and dev bundles, and it got solved by “standardising”
process.env.NODE_ENV == production|development. There is no standard for the environment itself, thus even such experienced developers as Sindre are looking for a special API to solve the problem.
That is a wrong way.
I do have another article about solving SSR related issues, again with mocking:
SSR: Dependency mocking is the answer!
Or breaking free from side effects and singletons in nodejs and webpack. Long story short – let me explain some things…
So – the task today is to separate code between browser and node environment:
- Separate it by files (you may just export needed API via these “temporal” files.
- Create index.js which would conditionally import one or another file.
- Think how to separate – there is no static variable you may rely on.
- Replace index.js by package.json and use it powers to do the job.
Package.json always has that “environment” switch we are looking for. There is no need for a magic variable, a special(and standard) API to “lazy” require something — only a different way to STRUCTURE your code.
That is all. And this is the same mocking you may know as “dependency mocking”. It’s not about testing and stubbing, but about saving your day.
Easy to mock code – easy to use code.
Separate concerns by files and directories and be happy.