Is there some documentation or best practice that supports or justifies this plan?
You might want to review Role Interfaces. The high level summary here being that most of your code (the consumer) should be focusing on what it wants done, with only a little bit being aware that UserManager[T]
is how you do it. Instead of trying to do everything with a single "general-purpose" interface, we define specialized interfaces that focus on expressing a single idea very well.
That might mean that instead of accepting a single general purpose interface as an argument, you instead accept several special purpose "role interfaces".
With the role interfaces defined, we now need implementations of them. Typically, we end up with something like the Adapter pattern in play; we have some sort of factory method that accepts a UserManager[T] as an argument and returns an adapter. The adapter itself simply translates between the role protocol and the user manager protocol.
We get two benefits out of this right away. First, the role interfaces are typically a lot simpler than the UserManager, and therefore they are simpler to mock. Second, the amount of code that depends on the UserManager abstraction is greatly reduced.
To some degree, this is a shell game - we're still making the same calls to UserManager that we were before. But what we have done is created a boundary (our role interfaces) between our bespoke code (which is complicated, and needs to be tested) and the UserManager (which makes things difficult to test).
The adapters themselves use only a small slice of the user manager. The implementation of the adapters are sensitive to changes in the behavior of the UserManager... but the UserManager code is (For the most part) stable. Because the code is simple and stable, we don't expect to invest a lot in refactoring further - think "throw it away". This shifts the distribution of risk quite a bit, and in turn means that we can target the adapters with different testing strategies than we use in our more complicated core (including, potentially, choosing not to directly test the adapters).
In short "don't mock what you don't own" is intended, in part, to remind you to create more things that you are "allowed" to mock. The "thing you don't own" then becomes a hidden implementation detail of a small part of your system.