As such, to perhaps help with the conversation, I'd like to have a practical example we can look at and compare potential solutions. Perhaps from WANObjectCache, or perhaps with something else.
Simetrical can speak on the concrete use case, but I'd like to give my thoughts on mocking WANObjectCache in general: when writing a unit test, the class under test should ideally be tested in isolation - that is, any of its dependencies should be mocked. If the dependency is inconsequential or there is a trivial implementation available, we don't have to be too strict about this. But complex dependencies should be avoided in unit tests, otherwise it's not a unit test but an integration test.
WANObjectCache is 2600 lines of complex code. When testing something that has a WANObjectCache injected, we should inject a fake WANObjectCache, to preserve the level of isolation that makes the test a unit test. As long as WANObjectCache's most important methods, like get(), are final, this is impossible.
I agree by the way that overly specific mocks go against the idea of a unit test. The test should test the contract, not the implementation. The mock should provide the minimum functionality needed by the code, it shouldn't assert things like "get() is called only once" - unless that is indeed part of the contract.
Narrow interfaces help with that. If we had for instance a cache interface that defined just the get() and set() methods, and that's all the code needs, then we can just provide a mock for that interface, and we wouldn't have to worry about WANObjectCache or its final methods at all.