|
Mocking everything is the unwise conventional wisdom. It complicates the code base for no discernible benefit. In practice, mocks are only useful for external dependencies, and computationally heavy internal dependencies. Possibly not even the latter. Why external dependencies are a good thing to mock is not just related to testing, it's related to code rot: external dependencies tend to change under your feet, so isolating them from your code base is a good thing, especially if you want to minimise vendor lock in. And for tests, it helps you simplify the test environment. Internal dependencies aren't like that: they only change if you change them, and they're already part of your environment. Mocking them just complicates your code without simplifying your tests. --- Now there is this idea that modules should be tested "in isolation". Imagine you have three classes, A, B and C, such that A uses B, and B uses C (and C is self contained). Without mocking, testing A will automatically involve B's and C's code as well. Mocking lets you test A alone, without the distraction of B and C. This is mostly bullshit. If A depends on B all the time, there's no point into making B a parameter (dependency injection). It's simpler to just hard code the dependency. As for the tests, who cares about isolation? If A is only used when it depends on B, there's no point in testing it under other conditions. More generally, it is okay to pull in the transitive closure of dependencies when you test a component. Of course, you should have tested each dependency (C, then B) before you test your module (A). That way you can mostly ensure the absence of bugs in the dependencies. For instance, if the tests for C and B succeed, and the test for A fails, the bug is probably in A. The order of the tests also matters for the test suite: if the tests for the dependencies are ran first, the first failed test should point to the failed module (instead of a user of the failed module). Now if your program is highly stateful, you might have to mock. Testing a highly stateful program without mocking requires setting lots of bits of states, and making sure all the pieces of runtime state interact with each other as they are supposed to. But then the problem isn't the lack of mocking, it's the fact your program is highly stateful in the first place. Make your program less stateful, first, then it will no longer need mocking. --- There is this mistaken notion that we should mock because if we don't, we're no longer making unit tests, we're making integration tests. The answer to that is simple: unit tests aren't the holy grail they are touted to be. Don't force them. If the dependencies are well tested (which they should be), then you can trust them like you would the standard library. Besides, the integration tests will catch more bugs for less effort than pure unit tests (with mocking) would have done. Don't waste your time with mocking, just go catch the bugs. |