> you seem to be assuming that I was suggesting the Fake should only implement the happy path
There is no such assumption. The assumption is that if you rely on a fake to service all your testing needs it cannot be tested against the real implementation as, in many cases, you do not want it to work the same way.
I don't know if a network connection failure is the greatest example, but let's run with it. Why bother adding simulated network failure into your fake, which, due to the problems you point out, won't be touched by your double-duty test suite anyway, when you can just create an additional mock that does nothing but simulate network failure? Why add needless complexity to the fake? You haven't gained a testability advantage.
That's not to say that a fake isn't also useful, but you haven't made a case for why it has to be the be all and end all. You can use both.
Let's imagine you hard-code a network failure in your fake for a particular domain, say "this-domain-fails.com", but it otherwise "works" for all the other domains. While your double-duty test can't confirm that your real implementation handles the failure properly, it will confirm that your fake otherwise works quite similar to the real implementation for other domains. And you'd test the failure condition with a separate test with the fake set up in exactly the same way as in the double duty test (eg. with a fixture).
And sure, this does not gain any testability advantage compared to a mock, but if your test for the failure uses as much as possible of the same code paths as the real implementation, only substituting the fake in, you increase trustworthiness — if the APIs between a fake and a real implementation diverge (a common problem with mocks as tests continue to pass), it's likely to be caught by the double-duty test, and as you adapt your fake to match the new reality, you'll likely start getting the network-failure test to fail too.
In the above example, the only bits you can't fully trust, since it's not automatically tested for both implementations, is your "emulation" of the failure: you want to be careful about how you implement that so it really happens in comparable circumstances to the real implementation (eg. it's ok to throw an error where you would otherwise be calling out over network and returning data).
A lot of it depends on how you structure the code. In memory database fakes are the easiest examples, because it's clear to most people how you can structure the code to have a facade API that's used everywhere, and only have the final fake/real implementations that either do stuff in-memory or on the actual database. But you can generally do that with anything.
In general, testing is never equivalent to proving code works correctly, but I think this is the closest you can get (with a healthy dose of fuzzing on top).
However I found most software engineers not to believe it to be possible or doable with not much effort to achieve this level of trust in the code. But "showing the code" has managed to convince most — it does require a switch in the mindset, but it's quite similar to accepting that real TDD is possible for anything but toy problems (I don't think it's the most efficient way to develop, but I think it is possible and teaches people to write testable code).
There is no such assumption. The assumption is that if you rely on a fake to service all your testing needs it cannot be tested against the real implementation as, in many cases, you do not want it to work the same way.
I don't know if a network connection failure is the greatest example, but let's run with it. Why bother adding simulated network failure into your fake, which, due to the problems you point out, won't be touched by your double-duty test suite anyway, when you can just create an additional mock that does nothing but simulate network failure? Why add needless complexity to the fake? You haven't gained a testability advantage.
That's not to say that a fake isn't also useful, but you haven't made a case for why it has to be the be all and end all. You can use both.