> Yes, but you can write integration tests instead. There’s no rule that says that unit testing must cover every aspect of the software. Unit test those units that can be used in isolation, integration test the rest. Case in point, our main software at work, written in C++, has close to 100% test coverage, and uses almost no mock tests. Instead, we have extensive integration tests where unit testing without mocking doesn’t work.

In my last C++ job, perhaps less than 5% of our code was unit testable. We had very good test coverage using integrated tests, but those were very expensive tests. Running a full test suite took 10 hours. Our SW heavily relied on certain equipment. Fortunately, the vendor had provided a very good simulator for it - so almost all our integration tests needed that simulator. And the simulator was such that there was a fair amount of overhead in loading and setting it up and unloading it. We didn't do this for every test - that would have taken days/weeks to run - but for logically grouped tests. And unfortunately many of the integration tests we wrote were much more suited to unit tests, but because we didn't have interfaces, we were forced to test them via an integration test, which was very expensive.

Oh, and the simulator would not allow parallelism - you could have only one simulator running on a given machine at a time. So all our tests had to be run in sequence.

And of course, the simulator had bugs, so whenever we had a failure, we had to determine if the simulator was at fault. Especially for intermittent failures.

So yes, we had very thorough tests and were proud of it, but unit testing for perhaps 30% of our tests would have been better. But to unit test those we really needed interfaces. I know because I convinced management to give me some weeks to convert one of our simplest portions of code into something we could unit test. I thought it would be trivial, but I ended up needing interfaces.

There is a whole other approach which our sister team (very similar SW, but different HW) used. They did not have a reliable simulator. So they wrote a "fake" simulator. They simply reproduced the APIs and wrote code to return certain values under certain conditions - a poor man's mock. On the plus side their test suite ran very quickly. The down side was they needed to write many mocks for the same function (for when they needed to return different values). Writing tests was very expensive for them.

Why did they write fakes instead of using a mocking framework? Because every mocking framework they found in C++ required interfaces, and they didn't want to change their SW architecture.

In many cases integration tests are OK. But in our case, they were extremely expensive.

> Incidentally this is vastly easier when the architecture cleanly separates business logic from general logic and moves as much of it as possible into side-effect free general-purpose functions.

This is precisely where interfaces come from! It's not trivial to separate business logic from general logic without them. When I took the time to show how we could write unit tests for our code base, I ended up with interfaces. And no, I didn't read any books/sites telling me I should do it. I didn't even know they were called interfaces. I just took some of the simplest code in our codebase, and asked "How can I write unit tests for this?" and essentially reinvented interfaces. I separated the business logic from the logic requiring the simulator, and then wrote unit tests for the business logic, and had an interface class to interface with the simulator.

To give you an idea, the code I converted to unit tests was trivial: Given this input string with these flags set, return this converted string, etc. It should be one of the easiest things to unit test! However, the input string and flags were entities understood by the HW and so we had simulator dependencies. I wrote a class that dealt only with strings and booleans to implement the business logic, and then had the interface class translate back and forth between strings/bools to entities the simulator expected/understood.

I appreciate your comment, and trust me, I'm not trying to be difficult. But while I've heard many claims, every time I've gone into the details I end up with interface classes. I work at a large company and went around asking several teams in different C++ projects, and they all independently had come to the same conclusion: Either use interfaces or live without unit tests. I presented my work to convert portions of our code base to unit tests at internal SW conferences, and would say "This is a highly nontrivial and crappy way to do unit tests in C++. I'd really like to hear from people in the audience if they found a better way." And whoever approached me afterwards said they had gone down the same path as me and ended up with interfaces.

Testing in C++ sucks, to be frank.

As an aside, I'm not pro-mocks, BTW. I recently did a small personal Python project where I insisted doing TDD. I would not write code till I had a test. And this involved several mocks. And while all my tests involving mocks passed, in the majority of cases involving the mocked code, my program had bugs and would fail when I tested with real data.

(Maybe that's more a criticism of TDD than of mocks, though).